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    if (replacement != 0) {
134	if (replacement < XML_MAX_TEXT_LENGTH)
135	    return(0);
136
137        /*
138	 * If the volume of entity copy reaches 10 times the
139	 * amount of parsed data and over the large text threshold
140	 * then that's very likely to be an abuse.
141	 */
142        if (ctxt->input != NULL) {
143	    consumed = ctxt->input->consumed +
144	               (ctxt->input->cur - ctxt->input->base);
145	}
146        consumed += ctxt->sizeentities;
147
148        if (replacement < XML_PARSER_NON_LINEAR * consumed)
149	    return(0);
150    } else if (size != 0) {
151        /*
152         * Do the check based on the replacement size of the entity
153         */
154        if (size < XML_PARSER_BIG_ENTITY)
155	    return(0);
156
157        /*
158         * A limit on the amount of text data reasonably used
159         */
160        if (ctxt->input != NULL) {
161            consumed = ctxt->input->consumed +
162                (ctxt->input->cur - ctxt->input->base);
163        }
164        consumed += ctxt->sizeentities;
165
166        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
167	    (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
168            return (0);
169    } else if (ent != NULL) {
170        /*
171         * use the number of parsed entities in the replacement
172         */
173        size = ent->checked / 2;
174
175        /*
176         * The amount of data parsed counting entities size only once
177         */
178        if (ctxt->input != NULL) {
179            consumed = ctxt->input->consumed +
180                (ctxt->input->cur - ctxt->input->base);
181        }
182        consumed += ctxt->sizeentities;
183
184        /*
185         * Check the density of entities for the amount of data
186	 * knowing an entity reference will take at least 3 bytes
187         */
188        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
189            return (0);
190    } else {
191        /*
192         * strange we got no data for checking just return
193         */
194        return (0);
195    }
196    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
197    return (1);
198}
199
200/**
201 * xmlParserMaxDepth:
202 *
203 * arbitrary depth limit for the XML documents that we allow to
204 * process. This is not a limitation of the parser but a safety
205 * boundary feature. It can be disabled with the XML_PARSE_HUGE
206 * parser option.
207 */
208unsigned int xmlParserMaxDepth = 256;
209
210
211
212#define SAX2 1
213#define XML_PARSER_BIG_BUFFER_SIZE 300
214#define XML_PARSER_BUFFER_SIZE 100
215#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
216
217/**
218 * XML_PARSER_CHUNK_SIZE
219 *
220 * When calling GROW that's the minimal amount of data
221 * the parser expected to have received. It is not a hard
222 * limit but an optimization when reading strings like Names
223 * It is not strictly needed as long as inputs available characters
224 * are followed by 0, which should be provided by the I/O level
225 */
226#define XML_PARSER_CHUNK_SIZE 100
227
228/*
229 * List of XML prefixed PI allowed by W3C specs
230 */
231
232static const char *xmlW3CPIs[] = {
233    "xml-stylesheet",
234    "xml-model",
235    NULL
236};
237
238
239/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
240static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
241                                              const xmlChar **str);
242
243static xmlParserErrors
244xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
245	              xmlSAXHandlerPtr sax,
246		      void *user_data, int depth, const xmlChar *URL,
247		      const xmlChar *ID, xmlNodePtr *list);
248
249static int
250xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
251                          const char *encoding);
252#ifdef LIBXML_LEGACY_ENABLED
253static void
254xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
255                      xmlNodePtr lastNode);
256#endif /* LIBXML_LEGACY_ENABLED */
257
258static xmlParserErrors
259xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
260		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
261
262static int
263xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
264
265/************************************************************************
266 *									*
267 *		Some factorized error routines				*
268 *									*
269 ************************************************************************/
270
271/**
272 * xmlErrAttributeDup:
273 * @ctxt:  an XML parser context
274 * @prefix:  the attribute prefix
275 * @localname:  the attribute localname
276 *
277 * Handle a redefinition of attribute error
278 */
279static void
280xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
281                   const xmlChar * localname)
282{
283    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
284        (ctxt->instate == XML_PARSER_EOF))
285	return;
286    if (ctxt != NULL)
287	ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
288
289    if (prefix == NULL)
290        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
291                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
292                        (const char *) localname, NULL, NULL, 0, 0,
293                        "Attribute %s redefined\n", localname);
294    else
295        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
296                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
297                        (const char *) prefix, (const char *) localname,
298                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
299                        localname);
300    if (ctxt != NULL) {
301	ctxt->wellFormed = 0;
302	if (ctxt->recovery == 0)
303	    ctxt->disableSAX = 1;
304    }
305}
306
307/**
308 * xmlFatalErr:
309 * @ctxt:  an XML parser context
310 * @error:  the error number
311 * @extra:  extra information string
312 *
313 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
314 */
315static void
316xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
317{
318    const char *errmsg;
319    char errstr[129] = "";
320
321    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
322        (ctxt->instate == XML_PARSER_EOF))
323	return;
324    switch (error) {
325        case XML_ERR_INVALID_HEX_CHARREF:
326            errmsg = "CharRef: invalid hexadecimal value";
327            break;
328        case XML_ERR_INVALID_DEC_CHARREF:
329            errmsg = "CharRef: invalid decimal value";
330            break;
331        case XML_ERR_INVALID_CHARREF:
332            errmsg = "CharRef: invalid value";
333            break;
334        case XML_ERR_INTERNAL_ERROR:
335            errmsg = "internal error";
336            break;
337        case XML_ERR_PEREF_AT_EOF:
338            errmsg = "PEReference at end of document";
339            break;
340        case XML_ERR_PEREF_IN_PROLOG:
341            errmsg = "PEReference in prolog";
342            break;
343        case XML_ERR_PEREF_IN_EPILOG:
344            errmsg = "PEReference in epilog";
345            break;
346        case XML_ERR_PEREF_NO_NAME:
347            errmsg = "PEReference: no name";
348            break;
349        case XML_ERR_PEREF_SEMICOL_MISSING:
350            errmsg = "PEReference: expecting ';'";
351            break;
352        case XML_ERR_ENTITY_LOOP:
353            errmsg = "Detected an entity reference loop";
354            break;
355        case XML_ERR_ENTITY_NOT_STARTED:
356            errmsg = "EntityValue: \" or ' expected";
357            break;
358        case XML_ERR_ENTITY_PE_INTERNAL:
359            errmsg = "PEReferences forbidden in internal subset";
360            break;
361        case XML_ERR_ENTITY_NOT_FINISHED:
362            errmsg = "EntityValue: \" or ' expected";
363            break;
364        case XML_ERR_ATTRIBUTE_NOT_STARTED:
365            errmsg = "AttValue: \" or ' expected";
366            break;
367        case XML_ERR_LT_IN_ATTRIBUTE:
368            errmsg = "Unescaped '<' not allowed in attributes values";
369            break;
370        case XML_ERR_LITERAL_NOT_STARTED:
371            errmsg = "SystemLiteral \" or ' expected";
372            break;
373        case XML_ERR_LITERAL_NOT_FINISHED:
374            errmsg = "Unfinished System or Public ID \" or ' expected";
375            break;
376        case XML_ERR_MISPLACED_CDATA_END:
377            errmsg = "Sequence ']]>' not allowed in content";
378            break;
379        case XML_ERR_URI_REQUIRED:
380            errmsg = "SYSTEM or PUBLIC, the URI is missing";
381            break;
382        case XML_ERR_PUBID_REQUIRED:
383            errmsg = "PUBLIC, the Public Identifier is missing";
384            break;
385        case XML_ERR_HYPHEN_IN_COMMENT:
386            errmsg = "Comment must not contain '--' (double-hyphen)";
387            break;
388        case XML_ERR_PI_NOT_STARTED:
389            errmsg = "xmlParsePI : no target name";
390            break;
391        case XML_ERR_RESERVED_XML_NAME:
392            errmsg = "Invalid PI name";
393            break;
394        case XML_ERR_NOTATION_NOT_STARTED:
395            errmsg = "NOTATION: Name expected here";
396            break;
397        case XML_ERR_NOTATION_NOT_FINISHED:
398            errmsg = "'>' required to close NOTATION declaration";
399            break;
400        case XML_ERR_VALUE_REQUIRED:
401            errmsg = "Entity value required";
402            break;
403        case XML_ERR_URI_FRAGMENT:
404            errmsg = "Fragment not allowed";
405            break;
406        case XML_ERR_ATTLIST_NOT_STARTED:
407            errmsg = "'(' required to start ATTLIST enumeration";
408            break;
409        case XML_ERR_NMTOKEN_REQUIRED:
410            errmsg = "NmToken expected in ATTLIST enumeration";
411            break;
412        case XML_ERR_ATTLIST_NOT_FINISHED:
413            errmsg = "')' required to finish ATTLIST enumeration";
414            break;
415        case XML_ERR_MIXED_NOT_STARTED:
416            errmsg = "MixedContentDecl : '|' or ')*' expected";
417            break;
418        case XML_ERR_PCDATA_REQUIRED:
419            errmsg = "MixedContentDecl : '#PCDATA' expected";
420            break;
421        case XML_ERR_ELEMCONTENT_NOT_STARTED:
422            errmsg = "ContentDecl : Name or '(' expected";
423            break;
424        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
425            errmsg = "ContentDecl : ',' '|' or ')' expected";
426            break;
427        case XML_ERR_PEREF_IN_INT_SUBSET:
428            errmsg =
429                "PEReference: forbidden within markup decl in internal subset";
430            break;
431        case XML_ERR_GT_REQUIRED:
432            errmsg = "expected '>'";
433            break;
434        case XML_ERR_CONDSEC_INVALID:
435            errmsg = "XML conditional section '[' expected";
436            break;
437        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
438            errmsg = "Content error in the external subset";
439            break;
440        case XML_ERR_CONDSEC_INVALID_KEYWORD:
441            errmsg =
442                "conditional section INCLUDE or IGNORE keyword expected";
443            break;
444        case XML_ERR_CONDSEC_NOT_FINISHED:
445            errmsg = "XML conditional section not closed";
446            break;
447        case XML_ERR_XMLDECL_NOT_STARTED:
448            errmsg = "Text declaration '<?xml' required";
449            break;
450        case XML_ERR_XMLDECL_NOT_FINISHED:
451            errmsg = "parsing XML declaration: '?>' expected";
452            break;
453        case XML_ERR_EXT_ENTITY_STANDALONE:
454            errmsg = "external parsed entities cannot be standalone";
455            break;
456        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
457            errmsg = "EntityRef: expecting ';'";
458            break;
459        case XML_ERR_DOCTYPE_NOT_FINISHED:
460            errmsg = "DOCTYPE improperly terminated";
461            break;
462        case XML_ERR_LTSLASH_REQUIRED:
463            errmsg = "EndTag: '</' not found";
464            break;
465        case XML_ERR_EQUAL_REQUIRED:
466            errmsg = "expected '='";
467            break;
468        case XML_ERR_STRING_NOT_CLOSED:
469            errmsg = "String not closed expecting \" or '";
470            break;
471        case XML_ERR_STRING_NOT_STARTED:
472            errmsg = "String not started expecting ' or \"";
473            break;
474        case XML_ERR_ENCODING_NAME:
475            errmsg = "Invalid XML encoding name";
476            break;
477        case XML_ERR_STANDALONE_VALUE:
478            errmsg = "standalone accepts only 'yes' or 'no'";
479            break;
480        case XML_ERR_DOCUMENT_EMPTY:
481            errmsg = "Document is empty";
482            break;
483        case XML_ERR_DOCUMENT_END:
484            errmsg = "Extra content at the end of the document";
485            break;
486        case XML_ERR_NOT_WELL_BALANCED:
487            errmsg = "chunk is not well balanced";
488            break;
489        case XML_ERR_EXTRA_CONTENT:
490            errmsg = "extra content at the end of well balanced chunk";
491            break;
492        case XML_ERR_VERSION_MISSING:
493            errmsg = "Malformed declaration expecting version";
494            break;
495        case XML_ERR_NAME_TOO_LONG:
496            errmsg = "Name too long use XML_PARSE_HUGE option";
497            break;
498#if 0
499        case:
500            errmsg = "";
501            break;
502#endif
503        default:
504            errmsg = "Unregistered error message";
505    }
506    if (info == NULL)
507        snprintf(errstr, 128, "%s\n", errmsg);
508    else
509        snprintf(errstr, 128, "%s: %%s\n", errmsg);
510    if (ctxt != NULL)
511	ctxt->errNo = error;
512    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
513                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
514                    info);
515    if (ctxt != NULL) {
516	ctxt->wellFormed = 0;
517	if (ctxt->recovery == 0)
518	    ctxt->disableSAX = 1;
519    }
520}
521
522/**
523 * xmlFatalErrMsg:
524 * @ctxt:  an XML parser context
525 * @error:  the error number
526 * @msg:  the error message
527 *
528 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
529 */
530static void
531xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
532               const char *msg)
533{
534    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
535        (ctxt->instate == XML_PARSER_EOF))
536	return;
537    if (ctxt != NULL)
538	ctxt->errNo = error;
539    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
540                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
541    if (ctxt != NULL) {
542	ctxt->wellFormed = 0;
543	if (ctxt->recovery == 0)
544	    ctxt->disableSAX = 1;
545    }
546}
547
548/**
549 * xmlWarningMsg:
550 * @ctxt:  an XML parser context
551 * @error:  the error number
552 * @msg:  the error message
553 * @str1:  extra data
554 * @str2:  extra data
555 *
556 * Handle a warning.
557 */
558static void
559xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
560              const char *msg, const xmlChar *str1, const xmlChar *str2)
561{
562    xmlStructuredErrorFunc schannel = NULL;
563
564    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
565        (ctxt->instate == XML_PARSER_EOF))
566	return;
567    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
568        (ctxt->sax->initialized == XML_SAX2_MAGIC))
569        schannel = ctxt->sax->serror;
570    if (ctxt != NULL) {
571        __xmlRaiseError(schannel,
572                    (ctxt->sax) ? ctxt->sax->warning : NULL,
573                    ctxt->userData,
574                    ctxt, NULL, XML_FROM_PARSER, error,
575                    XML_ERR_WARNING, NULL, 0,
576		    (const char *) str1, (const char *) str2, NULL, 0, 0,
577		    msg, (const char *) str1, (const char *) str2);
578    } else {
579        __xmlRaiseError(schannel, NULL, NULL,
580                    ctxt, NULL, XML_FROM_PARSER, error,
581                    XML_ERR_WARNING, NULL, 0,
582		    (const char *) str1, (const char *) str2, NULL, 0, 0,
583		    msg, (const char *) str1, (const char *) str2);
584    }
585}
586
587/**
588 * xmlValidityError:
589 * @ctxt:  an XML parser context
590 * @error:  the error number
591 * @msg:  the error message
592 * @str1:  extra data
593 *
594 * Handle a validity error.
595 */
596static void
597xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
598              const char *msg, const xmlChar *str1, const xmlChar *str2)
599{
600    xmlStructuredErrorFunc schannel = NULL;
601
602    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
603        (ctxt->instate == XML_PARSER_EOF))
604	return;
605    if (ctxt != NULL) {
606	ctxt->errNo = error;
607	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
608	    schannel = ctxt->sax->serror;
609    }
610    if (ctxt != NULL) {
611        __xmlRaiseError(schannel,
612                    ctxt->vctxt.error, ctxt->vctxt.userData,
613                    ctxt, NULL, XML_FROM_DTD, error,
614                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
615		    (const char *) str2, NULL, 0, 0,
616		    msg, (const char *) str1, (const char *) str2);
617	ctxt->valid = 0;
618    } else {
619        __xmlRaiseError(schannel, NULL, NULL,
620                    ctxt, NULL, XML_FROM_DTD, error,
621                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
622		    (const char *) str2, NULL, 0, 0,
623		    msg, (const char *) str1, (const char *) str2);
624    }
625}
626
627/**
628 * xmlFatalErrMsgInt:
629 * @ctxt:  an XML parser context
630 * @error:  the error number
631 * @msg:  the error message
632 * @val:  an integer value
633 *
634 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
635 */
636static void
637xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
638                  const char *msg, int val)
639{
640    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
641        (ctxt->instate == XML_PARSER_EOF))
642	return;
643    if (ctxt != NULL)
644	ctxt->errNo = error;
645    __xmlRaiseError(NULL, NULL, NULL,
646                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
647                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
648    if (ctxt != NULL) {
649	ctxt->wellFormed = 0;
650	if (ctxt->recovery == 0)
651	    ctxt->disableSAX = 1;
652    }
653}
654
655/**
656 * xmlFatalErrMsgStrIntStr:
657 * @ctxt:  an XML parser context
658 * @error:  the error number
659 * @msg:  the error message
660 * @str1:  an string info
661 * @val:  an integer value
662 * @str2:  an string info
663 *
664 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
665 */
666static void
667xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
668                  const char *msg, const xmlChar *str1, int val,
669		  const xmlChar *str2)
670{
671    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
672        (ctxt->instate == XML_PARSER_EOF))
673	return;
674    if (ctxt != NULL)
675	ctxt->errNo = error;
676    __xmlRaiseError(NULL, NULL, NULL,
677                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
678                    NULL, 0, (const char *) str1, (const char *) str2,
679		    NULL, val, 0, msg, str1, val, str2);
680    if (ctxt != NULL) {
681	ctxt->wellFormed = 0;
682	if (ctxt->recovery == 0)
683	    ctxt->disableSAX = 1;
684    }
685}
686
687/**
688 * xmlFatalErrMsgStr:
689 * @ctxt:  an XML parser context
690 * @error:  the error number
691 * @msg:  the error message
692 * @val:  a string value
693 *
694 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
695 */
696static void
697xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
698                  const char *msg, const xmlChar * val)
699{
700    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
701        (ctxt->instate == XML_PARSER_EOF))
702	return;
703    if (ctxt != NULL)
704	ctxt->errNo = error;
705    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
706                    XML_FROM_PARSER, error, XML_ERR_FATAL,
707                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
708                    val);
709    if (ctxt != NULL) {
710	ctxt->wellFormed = 0;
711	if (ctxt->recovery == 0)
712	    ctxt->disableSAX = 1;
713    }
714}
715
716/**
717 * xmlErrMsgStr:
718 * @ctxt:  an XML parser context
719 * @error:  the error number
720 * @msg:  the error message
721 * @val:  a string value
722 *
723 * Handle a non fatal parser error
724 */
725static void
726xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
727                  const char *msg, const xmlChar * val)
728{
729    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
730        (ctxt->instate == XML_PARSER_EOF))
731	return;
732    if (ctxt != NULL)
733	ctxt->errNo = error;
734    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
735                    XML_FROM_PARSER, error, XML_ERR_ERROR,
736                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
737                    val);
738}
739
740/**
741 * xmlNsErr:
742 * @ctxt:  an XML parser context
743 * @error:  the error number
744 * @msg:  the message
745 * @info1:  extra information string
746 * @info2:  extra information string
747 *
748 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
749 */
750static void
751xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
752         const char *msg,
753         const xmlChar * info1, const xmlChar * info2,
754         const xmlChar * info3)
755{
756    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
757        (ctxt->instate == XML_PARSER_EOF))
758	return;
759    if (ctxt != NULL)
760	ctxt->errNo = error;
761    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
762                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
763                    (const char *) info2, (const char *) info3, 0, 0, msg,
764                    info1, info2, info3);
765    if (ctxt != NULL)
766	ctxt->nsWellFormed = 0;
767}
768
769/**
770 * xmlNsWarn
771 * @ctxt:  an XML parser context
772 * @error:  the error number
773 * @msg:  the message
774 * @info1:  extra information string
775 * @info2:  extra information string
776 *
777 * Handle a namespace warning error
778 */
779static void
780xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
781         const char *msg,
782         const xmlChar * info1, const xmlChar * info2,
783         const xmlChar * info3)
784{
785    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
786        (ctxt->instate == XML_PARSER_EOF))
787	return;
788    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
789                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
790                    (const char *) info2, (const char *) info3, 0, 0, msg,
791                    info1, info2, info3);
792}
793
794/************************************************************************
795 *									*
796 *		Library wide options					*
797 *									*
798 ************************************************************************/
799
800/**
801  * xmlHasFeature:
802  * @feature: the feature to be examined
803  *
804  * Examines if the library has been compiled with a given feature.
805  *
806  * Returns a non-zero value if the feature exist, otherwise zero.
807  * Returns zero (0) if the feature does not exist or an unknown
808  * unknown feature is requested, non-zero otherwise.
809  */
810int
811xmlHasFeature(xmlFeature feature)
812{
813    switch (feature) {
814	case XML_WITH_THREAD:
815#ifdef LIBXML_THREAD_ENABLED
816	    return(1);
817#else
818	    return(0);
819#endif
820        case XML_WITH_TREE:
821#ifdef LIBXML_TREE_ENABLED
822            return(1);
823#else
824            return(0);
825#endif
826        case XML_WITH_OUTPUT:
827#ifdef LIBXML_OUTPUT_ENABLED
828            return(1);
829#else
830            return(0);
831#endif
832        case XML_WITH_PUSH:
833#ifdef LIBXML_PUSH_ENABLED
834            return(1);
835#else
836            return(0);
837#endif
838        case XML_WITH_READER:
839#ifdef LIBXML_READER_ENABLED
840            return(1);
841#else
842            return(0);
843#endif
844        case XML_WITH_PATTERN:
845#ifdef LIBXML_PATTERN_ENABLED
846            return(1);
847#else
848            return(0);
849#endif
850        case XML_WITH_WRITER:
851#ifdef LIBXML_WRITER_ENABLED
852            return(1);
853#else
854            return(0);
855#endif
856        case XML_WITH_SAX1:
857#ifdef LIBXML_SAX1_ENABLED
858            return(1);
859#else
860            return(0);
861#endif
862        case XML_WITH_FTP:
863#ifdef LIBXML_FTP_ENABLED
864            return(1);
865#else
866            return(0);
867#endif
868        case XML_WITH_HTTP:
869#ifdef LIBXML_HTTP_ENABLED
870            return(1);
871#else
872            return(0);
873#endif
874        case XML_WITH_VALID:
875#ifdef LIBXML_VALID_ENABLED
876            return(1);
877#else
878            return(0);
879#endif
880        case XML_WITH_HTML:
881#ifdef LIBXML_HTML_ENABLED
882            return(1);
883#else
884            return(0);
885#endif
886        case XML_WITH_LEGACY:
887#ifdef LIBXML_LEGACY_ENABLED
888            return(1);
889#else
890            return(0);
891#endif
892        case XML_WITH_C14N:
893#ifdef LIBXML_C14N_ENABLED
894            return(1);
895#else
896            return(0);
897#endif
898        case XML_WITH_CATALOG:
899#ifdef LIBXML_CATALOG_ENABLED
900            return(1);
901#else
902            return(0);
903#endif
904        case XML_WITH_XPATH:
905#ifdef LIBXML_XPATH_ENABLED
906            return(1);
907#else
908            return(0);
909#endif
910        case XML_WITH_XPTR:
911#ifdef LIBXML_XPTR_ENABLED
912            return(1);
913#else
914            return(0);
915#endif
916        case XML_WITH_XINCLUDE:
917#ifdef LIBXML_XINCLUDE_ENABLED
918            return(1);
919#else
920            return(0);
921#endif
922        case XML_WITH_ICONV:
923#ifdef LIBXML_ICONV_ENABLED
924            return(1);
925#else
926            return(0);
927#endif
928        case XML_WITH_ISO8859X:
929#ifdef LIBXML_ISO8859X_ENABLED
930            return(1);
931#else
932            return(0);
933#endif
934        case XML_WITH_UNICODE:
935#ifdef LIBXML_UNICODE_ENABLED
936            return(1);
937#else
938            return(0);
939#endif
940        case XML_WITH_REGEXP:
941#ifdef LIBXML_REGEXP_ENABLED
942            return(1);
943#else
944            return(0);
945#endif
946        case XML_WITH_AUTOMATA:
947#ifdef LIBXML_AUTOMATA_ENABLED
948            return(1);
949#else
950            return(0);
951#endif
952        case XML_WITH_EXPR:
953#ifdef LIBXML_EXPR_ENABLED
954            return(1);
955#else
956            return(0);
957#endif
958        case XML_WITH_SCHEMAS:
959#ifdef LIBXML_SCHEMAS_ENABLED
960            return(1);
961#else
962            return(0);
963#endif
964        case XML_WITH_SCHEMATRON:
965#ifdef LIBXML_SCHEMATRON_ENABLED
966            return(1);
967#else
968            return(0);
969#endif
970        case XML_WITH_MODULES:
971#ifdef LIBXML_MODULES_ENABLED
972            return(1);
973#else
974            return(0);
975#endif
976        case XML_WITH_DEBUG:
977#ifdef LIBXML_DEBUG_ENABLED
978            return(1);
979#else
980            return(0);
981#endif
982        case XML_WITH_DEBUG_MEM:
983#ifdef DEBUG_MEMORY_LOCATION
984            return(1);
985#else
986            return(0);
987#endif
988        case XML_WITH_DEBUG_RUN:
989#ifdef LIBXML_DEBUG_RUNTIME
990            return(1);
991#else
992            return(0);
993#endif
994        case XML_WITH_ZLIB:
995#ifdef LIBXML_ZLIB_ENABLED
996            return(1);
997#else
998            return(0);
999#endif
1000        case XML_WITH_LZMA:
1001#ifdef LIBXML_LZMA_ENABLED
1002            return(1);
1003#else
1004            return(0);
1005#endif
1006        case XML_WITH_ICU:
1007#ifdef LIBXML_ICU_ENABLED
1008            return(1);
1009#else
1010            return(0);
1011#endif
1012        default:
1013	    break;
1014     }
1015     return(0);
1016}
1017
1018/************************************************************************
1019 *									*
1020 *		SAX2 defaulted attributes handling			*
1021 *									*
1022 ************************************************************************/
1023
1024/**
1025 * xmlDetectSAX2:
1026 * @ctxt:  an XML parser context
1027 *
1028 * Do the SAX2 detection and specific intialization
1029 */
1030static void
1031xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
1032    if (ctxt == NULL) return;
1033#ifdef LIBXML_SAX1_ENABLED
1034    if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
1035        ((ctxt->sax->startElementNs != NULL) ||
1036         (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
1037#else
1038    ctxt->sax2 = 1;
1039#endif /* LIBXML_SAX1_ENABLED */
1040
1041    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
1042    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
1043    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
1044    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
1045		(ctxt->str_xml_ns == NULL)) {
1046        xmlErrMemory(ctxt, NULL);
1047    }
1048}
1049
1050typedef struct _xmlDefAttrs xmlDefAttrs;
1051typedef xmlDefAttrs *xmlDefAttrsPtr;
1052struct _xmlDefAttrs {
1053    int nbAttrs;	/* number of defaulted attributes on that element */
1054    int maxAttrs;       /* the size of the array */
1055    const xmlChar *values[5]; /* array of localname/prefix/values/external */
1056};
1057
1058/**
1059 * xmlAttrNormalizeSpace:
1060 * @src: the source string
1061 * @dst: the target string
1062 *
1063 * Normalize the space in non CDATA attribute values:
1064 * If the attribute type is not CDATA, then the XML processor MUST further
1065 * process the normalized attribute value by discarding any leading and
1066 * trailing space (#x20) characters, and by replacing sequences of space
1067 * (#x20) characters by a single space (#x20) character.
1068 * Note that the size of dst need to be at least src, and if one doesn't need
1069 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1070 * passing src as dst is just fine.
1071 *
1072 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1073 *         is needed.
1074 */
1075static xmlChar *
1076xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1077{
1078    if ((src == NULL) || (dst == NULL))
1079        return(NULL);
1080
1081    while (*src == 0x20) src++;
1082    while (*src != 0) {
1083	if (*src == 0x20) {
1084	    while (*src == 0x20) src++;
1085	    if (*src != 0)
1086		*dst++ = 0x20;
1087	} else {
1088	    *dst++ = *src++;
1089	}
1090    }
1091    *dst = 0;
1092    if (dst == src)
1093       return(NULL);
1094    return(dst);
1095}
1096
1097/**
1098 * xmlAttrNormalizeSpace2:
1099 * @src: the source string
1100 *
1101 * Normalize the space in non CDATA attribute values, a slightly more complex
1102 * front end to avoid allocation problems when running on attribute values
1103 * coming from the input.
1104 *
1105 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1106 *         is needed.
1107 */
1108static const xmlChar *
1109xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1110{
1111    int i;
1112    int remove_head = 0;
1113    int need_realloc = 0;
1114    const xmlChar *cur;
1115
1116    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1117        return(NULL);
1118    i = *len;
1119    if (i <= 0)
1120        return(NULL);
1121
1122    cur = src;
1123    while (*cur == 0x20) {
1124        cur++;
1125	remove_head++;
1126    }
1127    while (*cur != 0) {
1128	if (*cur == 0x20) {
1129	    cur++;
1130	    if ((*cur == 0x20) || (*cur == 0)) {
1131	        need_realloc = 1;
1132		break;
1133	    }
1134	} else
1135	    cur++;
1136    }
1137    if (need_realloc) {
1138        xmlChar *ret;
1139
1140	ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1141	if (ret == NULL) {
1142	    xmlErrMemory(ctxt, NULL);
1143	    return(NULL);
1144	}
1145	xmlAttrNormalizeSpace(ret, ret);
1146	*len = (int) strlen((const char *)ret);
1147        return(ret);
1148    } else if (remove_head) {
1149        *len -= remove_head;
1150        memmove(src, src + remove_head, 1 + *len);
1151	return(src);
1152    }
1153    return(NULL);
1154}
1155
1156/**
1157 * xmlAddDefAttrs:
1158 * @ctxt:  an XML parser context
1159 * @fullname:  the element fullname
1160 * @fullattr:  the attribute fullname
1161 * @value:  the attribute value
1162 *
1163 * Add a defaulted attribute for an element
1164 */
1165static void
1166xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1167               const xmlChar *fullname,
1168               const xmlChar *fullattr,
1169               const xmlChar *value) {
1170    xmlDefAttrsPtr defaults;
1171    int len;
1172    const xmlChar *name;
1173    const xmlChar *prefix;
1174
1175    /*
1176     * Allows to detect attribute redefinitions
1177     */
1178    if (ctxt->attsSpecial != NULL) {
1179        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1180	    return;
1181    }
1182
1183    if (ctxt->attsDefault == NULL) {
1184        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1185	if (ctxt->attsDefault == NULL)
1186	    goto mem_error;
1187    }
1188
1189    /*
1190     * split the element name into prefix:localname , the string found
1191     * are within the DTD and then not associated to namespace names.
1192     */
1193    name = xmlSplitQName3(fullname, &len);
1194    if (name == NULL) {
1195        name = xmlDictLookup(ctxt->dict, fullname, -1);
1196	prefix = NULL;
1197    } else {
1198        name = xmlDictLookup(ctxt->dict, name, -1);
1199	prefix = xmlDictLookup(ctxt->dict, fullname, len);
1200    }
1201
1202    /*
1203     * make sure there is some storage
1204     */
1205    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1206    if (defaults == NULL) {
1207        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1208	                   (4 * 5) * sizeof(const xmlChar *));
1209	if (defaults == NULL)
1210	    goto mem_error;
1211	defaults->nbAttrs = 0;
1212	defaults->maxAttrs = 4;
1213	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1214	                        defaults, NULL) < 0) {
1215	    xmlFree(defaults);
1216	    goto mem_error;
1217	}
1218    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1219        xmlDefAttrsPtr temp;
1220
1221        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1222		       (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1223	if (temp == NULL)
1224	    goto mem_error;
1225	defaults = temp;
1226	defaults->maxAttrs *= 2;
1227	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1228	                        defaults, NULL) < 0) {
1229	    xmlFree(defaults);
1230	    goto mem_error;
1231	}
1232    }
1233
1234    /*
1235     * Split the element name into prefix:localname , the string found
1236     * are within the DTD and hen not associated to namespace names.
1237     */
1238    name = xmlSplitQName3(fullattr, &len);
1239    if (name == NULL) {
1240        name = xmlDictLookup(ctxt->dict, fullattr, -1);
1241	prefix = NULL;
1242    } else {
1243        name = xmlDictLookup(ctxt->dict, name, -1);
1244	prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1245    }
1246
1247    defaults->values[5 * defaults->nbAttrs] = name;
1248    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1249    /* intern the string and precompute the end */
1250    len = xmlStrlen(value);
1251    value = xmlDictLookup(ctxt->dict, value, len);
1252    defaults->values[5 * defaults->nbAttrs + 2] = value;
1253    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1254    if (ctxt->external)
1255        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1256    else
1257        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1258    defaults->nbAttrs++;
1259
1260    return;
1261
1262mem_error:
1263    xmlErrMemory(ctxt, NULL);
1264    return;
1265}
1266
1267/**
1268 * xmlAddSpecialAttr:
1269 * @ctxt:  an XML parser context
1270 * @fullname:  the element fullname
1271 * @fullattr:  the attribute fullname
1272 * @type:  the attribute type
1273 *
1274 * Register this attribute type
1275 */
1276static void
1277xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1278		  const xmlChar *fullname,
1279		  const xmlChar *fullattr,
1280		  int type)
1281{
1282    if (ctxt->attsSpecial == NULL) {
1283        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1284	if (ctxt->attsSpecial == NULL)
1285	    goto mem_error;
1286    }
1287
1288    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1289        return;
1290
1291    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1292                     (void *) (long) type);
1293    return;
1294
1295mem_error:
1296    xmlErrMemory(ctxt, NULL);
1297    return;
1298}
1299
1300/**
1301 * xmlCleanSpecialAttrCallback:
1302 *
1303 * Removes CDATA attributes from the special attribute table
1304 */
1305static void
1306xmlCleanSpecialAttrCallback(void *payload, void *data,
1307                            const xmlChar *fullname, const xmlChar *fullattr,
1308                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1309    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1310
1311    if (((long) payload) == XML_ATTRIBUTE_CDATA) {
1312        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1313    }
1314}
1315
1316/**
1317 * xmlCleanSpecialAttr:
1318 * @ctxt:  an XML parser context
1319 *
1320 * Trim the list of attributes defined to remove all those of type
1321 * CDATA as they are not special. This call should be done when finishing
1322 * to parse the DTD and before starting to parse the document root.
1323 */
1324static void
1325xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1326{
1327    if (ctxt->attsSpecial == NULL)
1328        return;
1329
1330    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1331
1332    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1333        xmlHashFree(ctxt->attsSpecial, NULL);
1334        ctxt->attsSpecial = NULL;
1335    }
1336    return;
1337}
1338
1339/**
1340 * xmlCheckLanguageID:
1341 * @lang:  pointer to the string value
1342 *
1343 * Checks that the value conforms to the LanguageID production:
1344 *
1345 * NOTE: this is somewhat deprecated, those productions were removed from
1346 *       the XML Second edition.
1347 *
1348 * [33] LanguageID ::= Langcode ('-' Subcode)*
1349 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1350 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1351 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1352 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1353 * [38] Subcode ::= ([a-z] | [A-Z])+
1354 *
1355 * The current REC reference the sucessors of RFC 1766, currently 5646
1356 *
1357 * http://www.rfc-editor.org/rfc/rfc5646.txt
1358 * langtag       = language
1359 *                 ["-" script]
1360 *                 ["-" region]
1361 *                 *("-" variant)
1362 *                 *("-" extension)
1363 *                 ["-" privateuse]
1364 * language      = 2*3ALPHA            ; shortest ISO 639 code
1365 *                 ["-" extlang]       ; sometimes followed by
1366 *                                     ; extended language subtags
1367 *               / 4ALPHA              ; or reserved for future use
1368 *               / 5*8ALPHA            ; or registered language subtag
1369 *
1370 * extlang       = 3ALPHA              ; selected ISO 639 codes
1371 *                 *2("-" 3ALPHA)      ; permanently reserved
1372 *
1373 * script        = 4ALPHA              ; ISO 15924 code
1374 *
1375 * region        = 2ALPHA              ; ISO 3166-1 code
1376 *               / 3DIGIT              ; UN M.49 code
1377 *
1378 * variant       = 5*8alphanum         ; registered variants
1379 *               / (DIGIT 3alphanum)
1380 *
1381 * extension     = singleton 1*("-" (2*8alphanum))
1382 *
1383 *                                     ; Single alphanumerics
1384 *                                     ; "x" reserved for private use
1385 * singleton     = DIGIT               ; 0 - 9
1386 *               / %x41-57             ; A - W
1387 *               / %x59-5A             ; Y - Z
1388 *               / %x61-77             ; a - w
1389 *               / %x79-7A             ; y - z
1390 *
1391 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1392 * The parser below doesn't try to cope with extension or privateuse
1393 * that could be added but that's not interoperable anyway
1394 *
1395 * Returns 1 if correct 0 otherwise
1396 **/
1397int
1398xmlCheckLanguageID(const xmlChar * lang)
1399{
1400    const xmlChar *cur = lang, *nxt;
1401
1402    if (cur == NULL)
1403        return (0);
1404    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1405        ((cur[0] == 'I') && (cur[1] == '-')) ||
1406        ((cur[0] == 'x') && (cur[1] == '-')) ||
1407        ((cur[0] == 'X') && (cur[1] == '-'))) {
1408        /*
1409         * Still allow IANA code and user code which were coming
1410         * from the previous version of the XML-1.0 specification
1411         * it's deprecated but we should not fail
1412         */
1413        cur += 2;
1414        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1415               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1416            cur++;
1417        return(cur[0] == 0);
1418    }
1419    nxt = cur;
1420    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1421           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1422           nxt++;
1423    if (nxt - cur >= 4) {
1424        /*
1425         * Reserved
1426         */
1427        if ((nxt - cur > 8) || (nxt[0] != 0))
1428            return(0);
1429        return(1);
1430    }
1431    if (nxt - cur < 2)
1432        return(0);
1433    /* we got an ISO 639 code */
1434    if (nxt[0] == 0)
1435        return(1);
1436    if (nxt[0] != '-')
1437        return(0);
1438
1439    nxt++;
1440    cur = nxt;
1441    /* now we can have extlang or script or region or variant */
1442    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1443        goto region_m49;
1444
1445    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1446           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1447           nxt++;
1448    if (nxt - cur == 4)
1449        goto script;
1450    if (nxt - cur == 2)
1451        goto region;
1452    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1453        goto variant;
1454    if (nxt - cur != 3)
1455        return(0);
1456    /* we parsed an extlang */
1457    if (nxt[0] == 0)
1458        return(1);
1459    if (nxt[0] != '-')
1460        return(0);
1461
1462    nxt++;
1463    cur = nxt;
1464    /* now we can have script or region or variant */
1465    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1466        goto region_m49;
1467
1468    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1469           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1470           nxt++;
1471    if (nxt - cur == 2)
1472        goto region;
1473    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1474        goto variant;
1475    if (nxt - cur != 4)
1476        return(0);
1477    /* we parsed a script */
1478script:
1479    if (nxt[0] == 0)
1480        return(1);
1481    if (nxt[0] != '-')
1482        return(0);
1483
1484    nxt++;
1485    cur = nxt;
1486    /* now we can have region or variant */
1487    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1488        goto region_m49;
1489
1490    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1491           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1492           nxt++;
1493
1494    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1495        goto variant;
1496    if (nxt - cur != 2)
1497        return(0);
1498    /* we parsed a region */
1499region:
1500    if (nxt[0] == 0)
1501        return(1);
1502    if (nxt[0] != '-')
1503        return(0);
1504
1505    nxt++;
1506    cur = nxt;
1507    /* now we can just have a variant */
1508    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1509           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1510           nxt++;
1511
1512    if ((nxt - cur < 5) || (nxt - cur > 8))
1513        return(0);
1514
1515    /* we parsed a variant */
1516variant:
1517    if (nxt[0] == 0)
1518        return(1);
1519    if (nxt[0] != '-')
1520        return(0);
1521    /* extensions and private use subtags not checked */
1522    return (1);
1523
1524region_m49:
1525    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1526        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1527        nxt += 3;
1528        goto region;
1529    }
1530    return(0);
1531}
1532
1533/************************************************************************
1534 *									*
1535 *		Parser stacks related functions and macros		*
1536 *									*
1537 ************************************************************************/
1538
1539static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1540                                            const xmlChar ** str);
1541
1542#ifdef SAX2
1543/**
1544 * nsPush:
1545 * @ctxt:  an XML parser context
1546 * @prefix:  the namespace prefix or NULL
1547 * @URL:  the namespace name
1548 *
1549 * Pushes a new parser namespace on top of the ns stack
1550 *
1551 * Returns -1 in case of error, -2 if the namespace should be discarded
1552 *	   and the index in the stack otherwise.
1553 */
1554static int
1555nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1556{
1557    if (ctxt->options & XML_PARSE_NSCLEAN) {
1558        int i;
1559	for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
1560	    if (ctxt->nsTab[i] == prefix) {
1561		/* in scope */
1562	        if (ctxt->nsTab[i + 1] == URL)
1563		    return(-2);
1564		/* out of scope keep it */
1565		break;
1566	    }
1567	}
1568    }
1569    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1570	ctxt->nsMax = 10;
1571	ctxt->nsNr = 0;
1572	ctxt->nsTab = (const xmlChar **)
1573	              xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1574	if (ctxt->nsTab == NULL) {
1575	    xmlErrMemory(ctxt, NULL);
1576	    ctxt->nsMax = 0;
1577            return (-1);
1578	}
1579    } else if (ctxt->nsNr >= ctxt->nsMax) {
1580        const xmlChar ** tmp;
1581        ctxt->nsMax *= 2;
1582        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1583				    ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1584        if (tmp == NULL) {
1585            xmlErrMemory(ctxt, NULL);
1586	    ctxt->nsMax /= 2;
1587            return (-1);
1588        }
1589	ctxt->nsTab = tmp;
1590    }
1591    ctxt->nsTab[ctxt->nsNr++] = prefix;
1592    ctxt->nsTab[ctxt->nsNr++] = URL;
1593    return (ctxt->nsNr);
1594}
1595/**
1596 * nsPop:
1597 * @ctxt: an XML parser context
1598 * @nr:  the number to pop
1599 *
1600 * Pops the top @nr parser prefix/namespace from the ns stack
1601 *
1602 * Returns the number of namespaces removed
1603 */
1604static int
1605nsPop(xmlParserCtxtPtr ctxt, int nr)
1606{
1607    int i;
1608
1609    if (ctxt->nsTab == NULL) return(0);
1610    if (ctxt->nsNr < nr) {
1611        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1612        nr = ctxt->nsNr;
1613    }
1614    if (ctxt->nsNr <= 0)
1615        return (0);
1616
1617    for (i = 0;i < nr;i++) {
1618         ctxt->nsNr--;
1619	 ctxt->nsTab[ctxt->nsNr] = NULL;
1620    }
1621    return(nr);
1622}
1623#endif
1624
1625static int
1626xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1627    const xmlChar **atts;
1628    int *attallocs;
1629    int maxatts;
1630
1631    if (ctxt->atts == NULL) {
1632	maxatts = 55; /* allow for 10 attrs by default */
1633	atts = (const xmlChar **)
1634	       xmlMalloc(maxatts * sizeof(xmlChar *));
1635	if (atts == NULL) goto mem_error;
1636	ctxt->atts = atts;
1637	attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1638	if (attallocs == NULL) goto mem_error;
1639	ctxt->attallocs = attallocs;
1640	ctxt->maxatts = maxatts;
1641    } else if (nr + 5 > ctxt->maxatts) {
1642	maxatts = (nr + 5) * 2;
1643	atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1644				     maxatts * sizeof(const xmlChar *));
1645	if (atts == NULL) goto mem_error;
1646	ctxt->atts = atts;
1647	attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1648	                             (maxatts / 5) * sizeof(int));
1649	if (attallocs == NULL) goto mem_error;
1650	ctxt->attallocs = attallocs;
1651	ctxt->maxatts = maxatts;
1652    }
1653    return(ctxt->maxatts);
1654mem_error:
1655    xmlErrMemory(ctxt, NULL);
1656    return(-1);
1657}
1658
1659/**
1660 * inputPush:
1661 * @ctxt:  an XML parser context
1662 * @value:  the parser input
1663 *
1664 * Pushes a new parser input on top of the input stack
1665 *
1666 * Returns -1 in case of error, the index in the stack otherwise
1667 */
1668int
1669inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1670{
1671    if ((ctxt == NULL) || (value == NULL))
1672        return(-1);
1673    if (ctxt->inputNr >= ctxt->inputMax) {
1674        ctxt->inputMax *= 2;
1675        ctxt->inputTab =
1676            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1677                                             ctxt->inputMax *
1678                                             sizeof(ctxt->inputTab[0]));
1679        if (ctxt->inputTab == NULL) {
1680            xmlErrMemory(ctxt, NULL);
1681	    xmlFreeInputStream(value);
1682	    ctxt->inputMax /= 2;
1683	    value = NULL;
1684            return (-1);
1685        }
1686    }
1687    ctxt->inputTab[ctxt->inputNr] = value;
1688    ctxt->input = value;
1689    return (ctxt->inputNr++);
1690}
1691/**
1692 * inputPop:
1693 * @ctxt: an XML parser context
1694 *
1695 * Pops the top parser input from the input stack
1696 *
1697 * Returns the input just removed
1698 */
1699xmlParserInputPtr
1700inputPop(xmlParserCtxtPtr ctxt)
1701{
1702    xmlParserInputPtr ret;
1703
1704    if (ctxt == NULL)
1705        return(NULL);
1706    if (ctxt->inputNr <= 0)
1707        return (NULL);
1708    ctxt->inputNr--;
1709    if (ctxt->inputNr > 0)
1710        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1711    else
1712        ctxt->input = NULL;
1713    ret = ctxt->inputTab[ctxt->inputNr];
1714    ctxt->inputTab[ctxt->inputNr] = NULL;
1715    return (ret);
1716}
1717/**
1718 * nodePush:
1719 * @ctxt:  an XML parser context
1720 * @value:  the element node
1721 *
1722 * Pushes a new element node on top of the node stack
1723 *
1724 * Returns -1 in case of error, the index in the stack otherwise
1725 */
1726int
1727nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1728{
1729    if (ctxt == NULL) return(0);
1730    if (ctxt->nodeNr >= ctxt->nodeMax) {
1731        xmlNodePtr *tmp;
1732
1733	tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1734                                      ctxt->nodeMax * 2 *
1735                                      sizeof(ctxt->nodeTab[0]));
1736        if (tmp == NULL) {
1737            xmlErrMemory(ctxt, NULL);
1738            return (-1);
1739        }
1740        ctxt->nodeTab = tmp;
1741	ctxt->nodeMax *= 2;
1742    }
1743    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1744        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1745	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1746		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1747			  xmlParserMaxDepth);
1748	ctxt->instate = XML_PARSER_EOF;
1749	return(-1);
1750    }
1751    ctxt->nodeTab[ctxt->nodeNr] = value;
1752    ctxt->node = value;
1753    return (ctxt->nodeNr++);
1754}
1755
1756/**
1757 * nodePop:
1758 * @ctxt: an XML parser context
1759 *
1760 * Pops the top element node from the node stack
1761 *
1762 * Returns the node just removed
1763 */
1764xmlNodePtr
1765nodePop(xmlParserCtxtPtr ctxt)
1766{
1767    xmlNodePtr ret;
1768
1769    if (ctxt == NULL) return(NULL);
1770    if (ctxt->nodeNr <= 0)
1771        return (NULL);
1772    ctxt->nodeNr--;
1773    if (ctxt->nodeNr > 0)
1774        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1775    else
1776        ctxt->node = NULL;
1777    ret = ctxt->nodeTab[ctxt->nodeNr];
1778    ctxt->nodeTab[ctxt->nodeNr] = NULL;
1779    return (ret);
1780}
1781
1782#ifdef LIBXML_PUSH_ENABLED
1783/**
1784 * nameNsPush:
1785 * @ctxt:  an XML parser context
1786 * @value:  the element name
1787 * @prefix:  the element prefix
1788 * @URI:  the element namespace name
1789 *
1790 * Pushes a new element name/prefix/URL on top of the name stack
1791 *
1792 * Returns -1 in case of error, the index in the stack otherwise
1793 */
1794static int
1795nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1796           const xmlChar *prefix, const xmlChar *URI, int nsNr)
1797{
1798    if (ctxt->nameNr >= ctxt->nameMax) {
1799        const xmlChar * *tmp;
1800        void **tmp2;
1801        ctxt->nameMax *= 2;
1802        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1803                                    ctxt->nameMax *
1804                                    sizeof(ctxt->nameTab[0]));
1805        if (tmp == NULL) {
1806	    ctxt->nameMax /= 2;
1807	    goto mem_error;
1808        }
1809	ctxt->nameTab = tmp;
1810        tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
1811                                    ctxt->nameMax * 3 *
1812                                    sizeof(ctxt->pushTab[0]));
1813        if (tmp2 == NULL) {
1814	    ctxt->nameMax /= 2;
1815	    goto mem_error;
1816        }
1817	ctxt->pushTab = tmp2;
1818    }
1819    ctxt->nameTab[ctxt->nameNr] = value;
1820    ctxt->name = value;
1821    ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
1822    ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
1823    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
1824    return (ctxt->nameNr++);
1825mem_error:
1826    xmlErrMemory(ctxt, NULL);
1827    return (-1);
1828}
1829/**
1830 * nameNsPop:
1831 * @ctxt: an XML parser context
1832 *
1833 * Pops the top element/prefix/URI name from the name stack
1834 *
1835 * Returns the name just removed
1836 */
1837static const xmlChar *
1838nameNsPop(xmlParserCtxtPtr ctxt)
1839{
1840    const xmlChar *ret;
1841
1842    if (ctxt->nameNr <= 0)
1843        return (NULL);
1844    ctxt->nameNr--;
1845    if (ctxt->nameNr > 0)
1846        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1847    else
1848        ctxt->name = NULL;
1849    ret = ctxt->nameTab[ctxt->nameNr];
1850    ctxt->nameTab[ctxt->nameNr] = NULL;
1851    return (ret);
1852}
1853#endif /* LIBXML_PUSH_ENABLED */
1854
1855/**
1856 * namePush:
1857 * @ctxt:  an XML parser context
1858 * @value:  the element name
1859 *
1860 * Pushes a new element name on top of the name stack
1861 *
1862 * Returns -1 in case of error, the index in the stack otherwise
1863 */
1864int
1865namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1866{
1867    if (ctxt == NULL) return (-1);
1868
1869    if (ctxt->nameNr >= ctxt->nameMax) {
1870        const xmlChar * *tmp;
1871        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1872                                    ctxt->nameMax * 2 *
1873                                    sizeof(ctxt->nameTab[0]));
1874        if (tmp == NULL) {
1875	    goto mem_error;
1876        }
1877	ctxt->nameTab = tmp;
1878        ctxt->nameMax *= 2;
1879    }
1880    ctxt->nameTab[ctxt->nameNr] = value;
1881    ctxt->name = value;
1882    return (ctxt->nameNr++);
1883mem_error:
1884    xmlErrMemory(ctxt, NULL);
1885    return (-1);
1886}
1887/**
1888 * namePop:
1889 * @ctxt: an XML parser context
1890 *
1891 * Pops the top element name from the name stack
1892 *
1893 * Returns the name just removed
1894 */
1895const xmlChar *
1896namePop(xmlParserCtxtPtr ctxt)
1897{
1898    const xmlChar *ret;
1899
1900    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1901        return (NULL);
1902    ctxt->nameNr--;
1903    if (ctxt->nameNr > 0)
1904        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1905    else
1906        ctxt->name = NULL;
1907    ret = ctxt->nameTab[ctxt->nameNr];
1908    ctxt->nameTab[ctxt->nameNr] = NULL;
1909    return (ret);
1910}
1911
1912static int spacePush(xmlParserCtxtPtr ctxt, int val) {
1913    if (ctxt->spaceNr >= ctxt->spaceMax) {
1914        int *tmp;
1915
1916	ctxt->spaceMax *= 2;
1917        tmp = (int *) xmlRealloc(ctxt->spaceTab,
1918	                         ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
1919        if (tmp == NULL) {
1920	    xmlErrMemory(ctxt, NULL);
1921	    ctxt->spaceMax /=2;
1922	    return(-1);
1923	}
1924	ctxt->spaceTab = tmp;
1925    }
1926    ctxt->spaceTab[ctxt->spaceNr] = val;
1927    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
1928    return(ctxt->spaceNr++);
1929}
1930
1931static int spacePop(xmlParserCtxtPtr ctxt) {
1932    int ret;
1933    if (ctxt->spaceNr <= 0) return(0);
1934    ctxt->spaceNr--;
1935    if (ctxt->spaceNr > 0)
1936	ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
1937    else
1938        ctxt->space = &ctxt->spaceTab[0];
1939    ret = ctxt->spaceTab[ctxt->spaceNr];
1940    ctxt->spaceTab[ctxt->spaceNr] = -1;
1941    return(ret);
1942}
1943
1944/*
1945 * Macros for accessing the content. Those should be used only by the parser,
1946 * and not exported.
1947 *
1948 * Dirty macros, i.e. one often need to make assumption on the context to
1949 * use them
1950 *
1951 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
1952 *           To be used with extreme caution since operations consuming
1953 *           characters may move the input buffer to a different location !
1954 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
1955 *           This should be used internally by the parser
1956 *           only to compare to ASCII values otherwise it would break when
1957 *           running with UTF-8 encoding.
1958 *   RAW     same as CUR but in the input buffer, bypass any token
1959 *           extraction that may have been done
1960 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
1961 *           to compare on ASCII based substring.
1962 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1963 *           strings without newlines within the parser.
1964 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
1965 *           defined char within the parser.
1966 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1967 *
1968 *   NEXT    Skip to the next character, this does the proper decoding
1969 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
1970 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
1971 *   CUR_CHAR(l) returns the current unicode character (int), set l
1972 *           to the number of xmlChars used for the encoding [0-5].
1973 *   CUR_SCHAR  same but operate on a string instead of the context
1974 *   COPY_BUF  copy the current unicode char to the target buffer, increment
1975 *            the index
1976 *   GROW, SHRINK  handling of input buffers
1977 */
1978
1979#define RAW (*ctxt->input->cur)
1980#define CUR (*ctxt->input->cur)
1981#define NXT(val) ctxt->input->cur[(val)]
1982#define CUR_PTR ctxt->input->cur
1983
1984#define CMP4( s, c1, c2, c3, c4 ) \
1985  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
1986    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
1987#define CMP5( s, c1, c2, c3, c4, c5 ) \
1988  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
1989#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
1990  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
1991#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
1992  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
1993#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
1994  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
1995#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
1996  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
1997    ((unsigned char *) s)[ 8 ] == c9 )
1998#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
1999  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2000    ((unsigned char *) s)[ 9 ] == c10 )
2001
2002#define SKIP(val) do {							\
2003    ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);			\
2004    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2005    if ((*ctxt->input->cur == 0) &&					\
2006        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))		\
2007	    xmlPopInput(ctxt);						\
2008  } while (0)
2009
2010#define SKIPL(val) do {							\
2011    int skipl;								\
2012    for(skipl=0; skipl<val; skipl++) {					\
2013	if (*(ctxt->input->cur) == '\n') {				\
2014	ctxt->input->line++; ctxt->input->col = 1;			\
2015	} else ctxt->input->col++;					\
2016	ctxt->nbChars++;						\
2017	ctxt->input->cur++;						\
2018    }									\
2019    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2020    if ((*ctxt->input->cur == 0) &&					\
2021        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))		\
2022	    xmlPopInput(ctxt);						\
2023  } while (0)
2024
2025#define SHRINK if ((ctxt->progressive == 0) &&				\
2026		   (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2027		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2028	xmlSHRINK (ctxt);
2029
2030static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
2031    xmlParserInputShrink(ctxt->input);
2032    if ((*ctxt->input->cur == 0) &&
2033        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2034	    xmlPopInput(ctxt);
2035  }
2036
2037#define GROW if ((ctxt->progressive == 0) &&				\
2038		 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))	\
2039	xmlGROW (ctxt);
2040
2041static void xmlGROW (xmlParserCtxtPtr ctxt) {
2042    if ((((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
2043         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
2044         ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
2045        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2046        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
2047        ctxt->instate = XML_PARSER_EOF;
2048    }
2049    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2050    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
2051        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2052	    xmlPopInput(ctxt);
2053}
2054
2055#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2056
2057#define NEXT xmlNextChar(ctxt)
2058
2059#define NEXT1 {								\
2060	ctxt->input->col++;						\
2061	ctxt->input->cur++;						\
2062	ctxt->nbChars++;						\
2063	if (*ctxt->input->cur == 0)					\
2064	    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);		\
2065    }
2066
2067#define NEXTL(l) do {							\
2068    if (*(ctxt->input->cur) == '\n') {					\
2069	ctxt->input->line++; ctxt->input->col = 1;			\
2070    } else ctxt->input->col++;						\
2071    ctxt->input->cur += l;				\
2072    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2073  } while (0)
2074
2075#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2076#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2077
2078#define COPY_BUF(l,b,i,v)						\
2079    if (l == 1) b[i++] = (xmlChar) v;					\
2080    else i += xmlCopyCharMultiByte(&b[i],v)
2081
2082/**
2083 * xmlSkipBlankChars:
2084 * @ctxt:  the XML parser context
2085 *
2086 * skip all blanks character found at that point in the input streams.
2087 * It pops up finished entities in the process if allowable at that point.
2088 *
2089 * Returns the number of space chars skipped
2090 */
2091
2092int
2093xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2094    int res = 0;
2095
2096    /*
2097     * It's Okay to use CUR/NEXT here since all the blanks are on
2098     * the ASCII range.
2099     */
2100    if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
2101	const xmlChar *cur;
2102	/*
2103	 * if we are in the document content, go really fast
2104	 */
2105	cur = ctxt->input->cur;
2106	while (IS_BLANK_CH(*cur)) {
2107	    if (*cur == '\n') {
2108		ctxt->input->line++; ctxt->input->col = 1;
2109	    }
2110	    cur++;
2111	    res++;
2112	    if (*cur == 0) {
2113		ctxt->input->cur = cur;
2114		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2115		cur = ctxt->input->cur;
2116	    }
2117	}
2118	ctxt->input->cur = cur;
2119    } else {
2120	int cur;
2121	do {
2122	    cur = CUR;
2123	    while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
2124		NEXT;
2125		cur = CUR;
2126		res++;
2127	    }
2128	    while ((cur == 0) && (ctxt->inputNr > 1) &&
2129		   (ctxt->instate != XML_PARSER_COMMENT)) {
2130		xmlPopInput(ctxt);
2131		cur = CUR;
2132	    }
2133	    /*
2134	     * Need to handle support of entities branching here
2135	     */
2136	    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
2137	} while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
2138    }
2139    return(res);
2140}
2141
2142/************************************************************************
2143 *									*
2144 *		Commodity functions to handle entities			*
2145 *									*
2146 ************************************************************************/
2147
2148/**
2149 * xmlPopInput:
2150 * @ctxt:  an XML parser context
2151 *
2152 * xmlPopInput: the current input pointed by ctxt->input came to an end
2153 *          pop it and return the next char.
2154 *
2155 * Returns the current xmlChar in the parser context
2156 */
2157xmlChar
2158xmlPopInput(xmlParserCtxtPtr ctxt) {
2159    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2160    if (xmlParserDebugEntities)
2161	xmlGenericError(xmlGenericErrorContext,
2162		"Popping input %d\n", ctxt->inputNr);
2163    xmlFreeInputStream(inputPop(ctxt));
2164    if ((*ctxt->input->cur == 0) &&
2165        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2166	    return(xmlPopInput(ctxt));
2167    return(CUR);
2168}
2169
2170/**
2171 * xmlPushInput:
2172 * @ctxt:  an XML parser context
2173 * @input:  an XML parser input fragment (entity, XML fragment ...).
2174 *
2175 * xmlPushInput: switch to a new input stream which is stacked on top
2176 *               of the previous one(s).
2177 * Returns -1 in case of error or the index in the input stack
2178 */
2179int
2180xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2181    int ret;
2182    if (input == NULL) return(-1);
2183
2184    if (xmlParserDebugEntities) {
2185	if ((ctxt->input != NULL) && (ctxt->input->filename))
2186	    xmlGenericError(xmlGenericErrorContext,
2187		    "%s(%d): ", ctxt->input->filename,
2188		    ctxt->input->line);
2189	xmlGenericError(xmlGenericErrorContext,
2190		"Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2191    }
2192    ret = inputPush(ctxt, input);
2193    if (ctxt->instate == XML_PARSER_EOF)
2194        return(-1);
2195    GROW;
2196    return(ret);
2197}
2198
2199/**
2200 * xmlParseCharRef:
2201 * @ctxt:  an XML parser context
2202 *
2203 * parse Reference declarations
2204 *
2205 * [66] CharRef ::= '&#' [0-9]+ ';' |
2206 *                  '&#x' [0-9a-fA-F]+ ';'
2207 *
2208 * [ WFC: Legal Character ]
2209 * Characters referred to using character references must match the
2210 * production for Char.
2211 *
2212 * Returns the value parsed (as an int), 0 in case of error
2213 */
2214int
2215xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2216    unsigned int val = 0;
2217    int count = 0;
2218    unsigned int outofrange = 0;
2219
2220    /*
2221     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2222     */
2223    if ((RAW == '&') && (NXT(1) == '#') &&
2224        (NXT(2) == 'x')) {
2225	SKIP(3);
2226	GROW;
2227	while (RAW != ';') { /* loop blocked by count */
2228	    if (count++ > 20) {
2229		count = 0;
2230		GROW;
2231                if (ctxt->instate == XML_PARSER_EOF)
2232                    return(0);
2233	    }
2234	    if ((RAW >= '0') && (RAW <= '9'))
2235	        val = val * 16 + (CUR - '0');
2236	    else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2237	        val = val * 16 + (CUR - 'a') + 10;
2238	    else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2239	        val = val * 16 + (CUR - 'A') + 10;
2240	    else {
2241		xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2242		val = 0;
2243		break;
2244	    }
2245	    if (val > 0x10FFFF)
2246	        outofrange = val;
2247
2248	    NEXT;
2249	    count++;
2250	}
2251	if (RAW == ';') {
2252	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2253	    ctxt->input->col++;
2254	    ctxt->nbChars ++;
2255	    ctxt->input->cur++;
2256	}
2257    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2258	SKIP(2);
2259	GROW;
2260	while (RAW != ';') { /* loop blocked by count */
2261	    if (count++ > 20) {
2262		count = 0;
2263		GROW;
2264                if (ctxt->instate == XML_PARSER_EOF)
2265                    return(0);
2266	    }
2267	    if ((RAW >= '0') && (RAW <= '9'))
2268	        val = val * 10 + (CUR - '0');
2269	    else {
2270		xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2271		val = 0;
2272		break;
2273	    }
2274	    if (val > 0x10FFFF)
2275	        outofrange = val;
2276
2277	    NEXT;
2278	    count++;
2279	}
2280	if (RAW == ';') {
2281	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2282	    ctxt->input->col++;
2283	    ctxt->nbChars ++;
2284	    ctxt->input->cur++;
2285	}
2286    } else {
2287        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2288    }
2289
2290    /*
2291     * [ WFC: Legal Character ]
2292     * Characters referred to using character references must match the
2293     * production for Char.
2294     */
2295    if ((IS_CHAR(val) && (outofrange == 0))) {
2296        return(val);
2297    } else {
2298        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2299                          "xmlParseCharRef: invalid xmlChar value %d\n",
2300	                  val);
2301    }
2302    return(0);
2303}
2304
2305/**
2306 * xmlParseStringCharRef:
2307 * @ctxt:  an XML parser context
2308 * @str:  a pointer to an index in the string
2309 *
2310 * parse Reference declarations, variant parsing from a string rather
2311 * than an an input flow.
2312 *
2313 * [66] CharRef ::= '&#' [0-9]+ ';' |
2314 *                  '&#x' [0-9a-fA-F]+ ';'
2315 *
2316 * [ WFC: Legal Character ]
2317 * Characters referred to using character references must match the
2318 * production for Char.
2319 *
2320 * Returns the value parsed (as an int), 0 in case of error, str will be
2321 *         updated to the current value of the index
2322 */
2323static int
2324xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2325    const xmlChar *ptr;
2326    xmlChar cur;
2327    unsigned int val = 0;
2328    unsigned int outofrange = 0;
2329
2330    if ((str == NULL) || (*str == NULL)) return(0);
2331    ptr = *str;
2332    cur = *ptr;
2333    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2334	ptr += 3;
2335	cur = *ptr;
2336	while (cur != ';') { /* Non input consuming loop */
2337	    if ((cur >= '0') && (cur <= '9'))
2338	        val = val * 16 + (cur - '0');
2339	    else if ((cur >= 'a') && (cur <= 'f'))
2340	        val = val * 16 + (cur - 'a') + 10;
2341	    else if ((cur >= 'A') && (cur <= 'F'))
2342	        val = val * 16 + (cur - 'A') + 10;
2343	    else {
2344		xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2345		val = 0;
2346		break;
2347	    }
2348	    if (val > 0x10FFFF)
2349	        outofrange = val;
2350
2351	    ptr++;
2352	    cur = *ptr;
2353	}
2354	if (cur == ';')
2355	    ptr++;
2356    } else if  ((cur == '&') && (ptr[1] == '#')){
2357	ptr += 2;
2358	cur = *ptr;
2359	while (cur != ';') { /* Non input consuming loops */
2360	    if ((cur >= '0') && (cur <= '9'))
2361	        val = val * 10 + (cur - '0');
2362	    else {
2363		xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2364		val = 0;
2365		break;
2366	    }
2367	    if (val > 0x10FFFF)
2368	        outofrange = val;
2369
2370	    ptr++;
2371	    cur = *ptr;
2372	}
2373	if (cur == ';')
2374	    ptr++;
2375    } else {
2376	xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2377	return(0);
2378    }
2379    *str = ptr;
2380
2381    /*
2382     * [ WFC: Legal Character ]
2383     * Characters referred to using character references must match the
2384     * production for Char.
2385     */
2386    if ((IS_CHAR(val) && (outofrange == 0))) {
2387        return(val);
2388    } else {
2389        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2390			  "xmlParseStringCharRef: invalid xmlChar value %d\n",
2391			  val);
2392    }
2393    return(0);
2394}
2395
2396/**
2397 * xmlNewBlanksWrapperInputStream:
2398 * @ctxt:  an XML parser context
2399 * @entity:  an Entity pointer
2400 *
2401 * Create a new input stream for wrapping
2402 * blanks around a PEReference
2403 *
2404 * Returns the new input stream or NULL
2405 */
2406
2407static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
2408
2409static xmlParserInputPtr
2410xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
2411    xmlParserInputPtr input;
2412    xmlChar *buffer;
2413    size_t length;
2414    if (entity == NULL) {
2415	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2416	            "xmlNewBlanksWrapperInputStream entity\n");
2417	return(NULL);
2418    }
2419    if (xmlParserDebugEntities)
2420	xmlGenericError(xmlGenericErrorContext,
2421		"new blanks wrapper for entity: %s\n", entity->name);
2422    input = xmlNewInputStream(ctxt);
2423    if (input == NULL) {
2424	return(NULL);
2425    }
2426    length = xmlStrlen(entity->name) + 5;
2427    buffer = xmlMallocAtomic(length);
2428    if (buffer == NULL) {
2429	xmlErrMemory(ctxt, NULL);
2430        xmlFree(input);
2431	return(NULL);
2432    }
2433    buffer [0] = ' ';
2434    buffer [1] = '%';
2435    buffer [length-3] = ';';
2436    buffer [length-2] = ' ';
2437    buffer [length-1] = 0;
2438    memcpy(buffer + 2, entity->name, length - 5);
2439    input->free = deallocblankswrapper;
2440    input->base = buffer;
2441    input->cur = buffer;
2442    input->length = length;
2443    input->end = &buffer[length];
2444    return(input);
2445}
2446
2447/**
2448 * xmlParserHandlePEReference:
2449 * @ctxt:  the parser context
2450 *
2451 * [69] PEReference ::= '%' Name ';'
2452 *
2453 * [ WFC: No Recursion ]
2454 * A parsed entity must not contain a recursive
2455 * reference to itself, either directly or indirectly.
2456 *
2457 * [ WFC: Entity Declared ]
2458 * In a document without any DTD, a document with only an internal DTD
2459 * subset which contains no parameter entity references, or a document
2460 * with "standalone='yes'", ...  ... The declaration of a parameter
2461 * entity must precede any reference to it...
2462 *
2463 * [ VC: Entity Declared ]
2464 * In a document with an external subset or external parameter entities
2465 * with "standalone='no'", ...  ... The declaration of a parameter entity
2466 * must precede any reference to it...
2467 *
2468 * [ WFC: In DTD ]
2469 * Parameter-entity references may only appear in the DTD.
2470 * NOTE: misleading but this is handled.
2471 *
2472 * A PEReference may have been detected in the current input stream
2473 * the handling is done accordingly to
2474 *      http://www.w3.org/TR/REC-xml#entproc
2475 * i.e.
2476 *   - Included in literal in entity values
2477 *   - Included as Parameter Entity reference within DTDs
2478 */
2479void
2480xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2481    const xmlChar *name;
2482    xmlEntityPtr entity = NULL;
2483    xmlParserInputPtr input;
2484
2485    if (RAW != '%') return;
2486    switch(ctxt->instate) {
2487	case XML_PARSER_CDATA_SECTION:
2488	    return;
2489        case XML_PARSER_COMMENT:
2490	    return;
2491	case XML_PARSER_START_TAG:
2492	    return;
2493	case XML_PARSER_END_TAG:
2494	    return;
2495        case XML_PARSER_EOF:
2496	    xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2497	    return;
2498        case XML_PARSER_PROLOG:
2499	case XML_PARSER_START:
2500	case XML_PARSER_MISC:
2501	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2502	    return;
2503	case XML_PARSER_ENTITY_DECL:
2504        case XML_PARSER_CONTENT:
2505        case XML_PARSER_ATTRIBUTE_VALUE:
2506        case XML_PARSER_PI:
2507	case XML_PARSER_SYSTEM_LITERAL:
2508	case XML_PARSER_PUBLIC_LITERAL:
2509	    /* we just ignore it there */
2510	    return;
2511        case XML_PARSER_EPILOG:
2512	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2513	    return;
2514	case XML_PARSER_ENTITY_VALUE:
2515	    /*
2516	     * NOTE: in the case of entity values, we don't do the
2517	     *       substitution here since we need the literal
2518	     *       entity value to be able to save the internal
2519	     *       subset of the document.
2520	     *       This will be handled by xmlStringDecodeEntities
2521	     */
2522	    return;
2523        case XML_PARSER_DTD:
2524	    /*
2525	     * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2526	     * In the internal DTD subset, parameter-entity references
2527	     * can occur only where markup declarations can occur, not
2528	     * within markup declarations.
2529	     * In that case this is handled in xmlParseMarkupDecl
2530	     */
2531	    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2532		return;
2533	    if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2534		return;
2535            break;
2536        case XML_PARSER_IGNORE:
2537            return;
2538    }
2539
2540    NEXT;
2541    name = xmlParseName(ctxt);
2542    if (xmlParserDebugEntities)
2543	xmlGenericError(xmlGenericErrorContext,
2544		"PEReference: %s\n", name);
2545    if (name == NULL) {
2546	xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
2547    } else {
2548	if (RAW == ';') {
2549	    NEXT;
2550	    if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
2551		entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
2552	    if (ctxt->instate == XML_PARSER_EOF)
2553	        return;
2554	    if (entity == NULL) {
2555
2556		/*
2557		 * [ WFC: Entity Declared ]
2558		 * In a document without any DTD, a document with only an
2559		 * internal DTD subset which contains no parameter entity
2560		 * references, or a document with "standalone='yes'", ...
2561		 * ... The declaration of a parameter entity must precede
2562		 * any reference to it...
2563		 */
2564		if ((ctxt->standalone == 1) ||
2565		    ((ctxt->hasExternalSubset == 0) &&
2566		     (ctxt->hasPErefs == 0))) {
2567		    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
2568			 "PEReference: %%%s; not found\n", name);
2569	        } else {
2570		    /*
2571		     * [ VC: Entity Declared ]
2572		     * In a document with an external subset or external
2573		     * parameter entities with "standalone='no'", ...
2574		     * ... The declaration of a parameter entity must precede
2575		     * any reference to it...
2576		     */
2577		    if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
2578		        xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
2579			                 "PEReference: %%%s; not found\n",
2580				         name, NULL);
2581		    } else
2582		        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
2583			              "PEReference: %%%s; not found\n",
2584				      name, NULL);
2585		    ctxt->valid = 0;
2586		}
2587	    } else if (ctxt->input->free != deallocblankswrapper) {
2588		    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
2589		    if (xmlPushInput(ctxt, input) < 0)
2590		        return;
2591	    } else {
2592	        if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
2593		    (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
2594		    xmlChar start[4];
2595		    xmlCharEncoding enc;
2596
2597		    /*
2598		     * handle the extra spaces added before and after
2599		     * c.f. http://www.w3.org/TR/REC-xml#as-PE
2600		     * this is done independently.
2601		     */
2602		    input = xmlNewEntityInputStream(ctxt, entity);
2603		    if (xmlPushInput(ctxt, input) < 0)
2604		        return;
2605
2606		    /*
2607		     * Get the 4 first bytes and decode the charset
2608		     * if enc != XML_CHAR_ENCODING_NONE
2609		     * plug some encoding conversion routines.
2610		     * Note that, since we may have some non-UTF8
2611		     * encoding (like UTF16, bug 135229), the 'length'
2612		     * is not known, but we can calculate based upon
2613		     * the amount of data in the buffer.
2614		     */
2615		    GROW
2616                    if (ctxt->instate == XML_PARSER_EOF)
2617                        return;
2618		    if ((ctxt->input->end - ctxt->input->cur)>=4) {
2619			start[0] = RAW;
2620			start[1] = NXT(1);
2621			start[2] = NXT(2);
2622			start[3] = NXT(3);
2623			enc = xmlDetectCharEncoding(start, 4);
2624			if (enc != XML_CHAR_ENCODING_NONE) {
2625			    xmlSwitchEncoding(ctxt, enc);
2626			}
2627		    }
2628
2629		    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2630			(CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
2631			(IS_BLANK_CH(NXT(5)))) {
2632			xmlParseTextDecl(ctxt);
2633		    }
2634		} else {
2635		    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
2636			     "PEReference: %s is not a parameter entity\n",
2637				      name);
2638		}
2639	    }
2640	} else {
2641	    xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
2642	}
2643    }
2644}
2645
2646/*
2647 * Macro used to grow the current buffer.
2648 * buffer##_size is expected to be a size_t
2649 * mem_error: is expected to handle memory allocation failures
2650 */
2651#define growBuffer(buffer, n) {						\
2652    xmlChar *tmp;							\
2653    size_t new_size = buffer##_size * 2 + n;                            \
2654    if (new_size < buffer##_size) goto mem_error;                       \
2655    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2656    if (tmp == NULL) goto mem_error;					\
2657    buffer = tmp;							\
2658    buffer##_size = new_size;                                           \
2659}
2660
2661/**
2662 * xmlStringLenDecodeEntities:
2663 * @ctxt:  the parser context
2664 * @str:  the input string
2665 * @len: the string length
2666 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2667 * @end:  an end marker xmlChar, 0 if none
2668 * @end2:  an end marker xmlChar, 0 if none
2669 * @end3:  an end marker xmlChar, 0 if none
2670 *
2671 * Takes a entity string content and process to do the adequate substitutions.
2672 *
2673 * [67] Reference ::= EntityRef | CharRef
2674 *
2675 * [69] PEReference ::= '%' Name ';'
2676 *
2677 * Returns A newly allocated string with the substitution done. The caller
2678 *      must deallocate it !
2679 */
2680xmlChar *
2681xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2682		      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
2683    xmlChar *buffer = NULL;
2684    size_t buffer_size = 0;
2685    size_t nbchars = 0;
2686
2687    xmlChar *current = NULL;
2688    xmlChar *rep = NULL;
2689    const xmlChar *last;
2690    xmlEntityPtr ent;
2691    int c,l;
2692
2693    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2694	return(NULL);
2695    last = str + len;
2696
2697    if (((ctxt->depth > 40) &&
2698         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2699	(ctxt->depth > 1024)) {
2700	xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2701	return(NULL);
2702    }
2703
2704    /*
2705     * allocate a translation buffer.
2706     */
2707    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2708    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2709    if (buffer == NULL) goto mem_error;
2710
2711    /*
2712     * OK loop until we reach one of the ending char or a size limit.
2713     * we are operating on already parsed values.
2714     */
2715    if (str < last)
2716	c = CUR_SCHAR(str, l);
2717    else
2718        c = 0;
2719    while ((c != 0) && (c != end) && /* non input consuming loop */
2720	   (c != end2) && (c != end3)) {
2721
2722	if (c == 0) break;
2723        if ((c == '&') && (str[1] == '#')) {
2724	    int val = xmlParseStringCharRef(ctxt, &str);
2725	    if (val != 0) {
2726		COPY_BUF(0,buffer,nbchars,val);
2727	    }
2728	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2729	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2730	    }
2731	} else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2732	    if (xmlParserDebugEntities)
2733		xmlGenericError(xmlGenericErrorContext,
2734			"String decoding Entity Reference: %.30s\n",
2735			str);
2736	    ent = xmlParseStringEntityRef(ctxt, &str);
2737	    if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
2738	        (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
2739	        goto int_error;
2740	    if (ent != NULL)
2741	        ctxt->nbentities += ent->checked / 2;
2742	    if ((ent != NULL) &&
2743		(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2744		if (ent->content != NULL) {
2745		    COPY_BUF(0,buffer,nbchars,ent->content[0]);
2746		    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2747			growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2748		    }
2749		} else {
2750		    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2751			    "predefined entity has no content\n");
2752		}
2753	    } else if ((ent != NULL) && (ent->content != NULL)) {
2754		ctxt->depth++;
2755		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2756			                      0, 0, 0);
2757		ctxt->depth--;
2758
2759		if (rep != NULL) {
2760		    current = rep;
2761		    while (*current != 0) { /* non input consuming loop */
2762			buffer[nbchars++] = *current++;
2763			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2764			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2765				goto int_error;
2766			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2767			}
2768		    }
2769		    xmlFree(rep);
2770		    rep = NULL;
2771		}
2772	    } else if (ent != NULL) {
2773		int i = xmlStrlen(ent->name);
2774		const xmlChar *cur = ent->name;
2775
2776		buffer[nbchars++] = '&';
2777		if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2778		    growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2779		}
2780		for (;i > 0;i--)
2781		    buffer[nbchars++] = *cur++;
2782		buffer[nbchars++] = ';';
2783	    }
2784	} else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2785	    if (xmlParserDebugEntities)
2786		xmlGenericError(xmlGenericErrorContext,
2787			"String decoding PE Reference: %.30s\n", str);
2788	    ent = xmlParseStringPEReference(ctxt, &str);
2789	    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
2790	        goto int_error;
2791	    if (ent != NULL)
2792	        ctxt->nbentities += ent->checked / 2;
2793	    if (ent != NULL) {
2794                if (ent->content == NULL) {
2795		    xmlLoadEntityContent(ctxt, ent);
2796		}
2797		ctxt->depth++;
2798		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2799			                      0, 0, 0);
2800		ctxt->depth--;
2801		if (rep != NULL) {
2802		    current = rep;
2803		    while (*current != 0) { /* non input consuming loop */
2804			buffer[nbchars++] = *current++;
2805			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2806			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2807			        goto int_error;
2808			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2809			}
2810		    }
2811		    xmlFree(rep);
2812		    rep = NULL;
2813		}
2814	    }
2815	} else {
2816	    COPY_BUF(l,buffer,nbchars,c);
2817	    str += l;
2818	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2819	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2820	    }
2821	}
2822	if (str < last)
2823	    c = CUR_SCHAR(str, l);
2824	else
2825	    c = 0;
2826    }
2827    buffer[nbchars] = 0;
2828    return(buffer);
2829
2830mem_error:
2831    xmlErrMemory(ctxt, NULL);
2832int_error:
2833    if (rep != NULL)
2834        xmlFree(rep);
2835    if (buffer != NULL)
2836        xmlFree(buffer);
2837    return(NULL);
2838}
2839
2840/**
2841 * xmlStringDecodeEntities:
2842 * @ctxt:  the parser context
2843 * @str:  the input string
2844 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2845 * @end:  an end marker xmlChar, 0 if none
2846 * @end2:  an end marker xmlChar, 0 if none
2847 * @end3:  an end marker xmlChar, 0 if none
2848 *
2849 * Takes a entity string content and process to do the adequate substitutions.
2850 *
2851 * [67] Reference ::= EntityRef | CharRef
2852 *
2853 * [69] PEReference ::= '%' Name ';'
2854 *
2855 * Returns A newly allocated string with the substitution done. The caller
2856 *      must deallocate it !
2857 */
2858xmlChar *
2859xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2860		        xmlChar end, xmlChar  end2, xmlChar end3) {
2861    if ((ctxt == NULL) || (str == NULL)) return(NULL);
2862    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2863           end, end2, end3));
2864}
2865
2866/************************************************************************
2867 *									*
2868 *		Commodity functions, cleanup needed ?			*
2869 *									*
2870 ************************************************************************/
2871
2872/**
2873 * areBlanks:
2874 * @ctxt:  an XML parser context
2875 * @str:  a xmlChar *
2876 * @len:  the size of @str
2877 * @blank_chars: we know the chars are blanks
2878 *
2879 * Is this a sequence of blank chars that one can ignore ?
2880 *
2881 * Returns 1 if ignorable 0 otherwise.
2882 */
2883
2884static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2885                     int blank_chars) {
2886    int i, ret;
2887    xmlNodePtr lastChild;
2888
2889    /*
2890     * Don't spend time trying to differentiate them, the same callback is
2891     * used !
2892     */
2893    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2894	return(0);
2895
2896    /*
2897     * Check for xml:space value.
2898     */
2899    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2900        (*(ctxt->space) == -2))
2901	return(0);
2902
2903    /*
2904     * Check that the string is made of blanks
2905     */
2906    if (blank_chars == 0) {
2907	for (i = 0;i < len;i++)
2908	    if (!(IS_BLANK_CH(str[i]))) return(0);
2909    }
2910
2911    /*
2912     * Look if the element is mixed content in the DTD if available
2913     */
2914    if (ctxt->node == NULL) return(0);
2915    if (ctxt->myDoc != NULL) {
2916	ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2917        if (ret == 0) return(1);
2918        if (ret == 1) return(0);
2919    }
2920
2921    /*
2922     * Otherwise, heuristic :-\
2923     */
2924    if ((RAW != '<') && (RAW != 0xD)) return(0);
2925    if ((ctxt->node->children == NULL) &&
2926	(RAW == '<') && (NXT(1) == '/')) return(0);
2927
2928    lastChild = xmlGetLastChild(ctxt->node);
2929    if (lastChild == NULL) {
2930        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2931            (ctxt->node->content != NULL)) return(0);
2932    } else if (xmlNodeIsText(lastChild))
2933        return(0);
2934    else if ((ctxt->node->children != NULL) &&
2935             (xmlNodeIsText(ctxt->node->children)))
2936        return(0);
2937    return(1);
2938}
2939
2940/************************************************************************
2941 *									*
2942 *		Extra stuff for namespace support			*
2943 *	Relates to http://www.w3.org/TR/WD-xml-names			*
2944 *									*
2945 ************************************************************************/
2946
2947/**
2948 * xmlSplitQName:
2949 * @ctxt:  an XML parser context
2950 * @name:  an XML parser context
2951 * @prefix:  a xmlChar **
2952 *
2953 * parse an UTF8 encoded XML qualified name string
2954 *
2955 * [NS 5] QName ::= (Prefix ':')? LocalPart
2956 *
2957 * [NS 6] Prefix ::= NCName
2958 *
2959 * [NS 7] LocalPart ::= NCName
2960 *
2961 * Returns the local part, and prefix is updated
2962 *   to get the Prefix if any.
2963 */
2964
2965xmlChar *
2966xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2967    xmlChar buf[XML_MAX_NAMELEN + 5];
2968    xmlChar *buffer = NULL;
2969    int len = 0;
2970    int max = XML_MAX_NAMELEN;
2971    xmlChar *ret = NULL;
2972    const xmlChar *cur = name;
2973    int c;
2974
2975    if (prefix == NULL) return(NULL);
2976    *prefix = NULL;
2977
2978    if (cur == NULL) return(NULL);
2979
2980#ifndef XML_XML_NAMESPACE
2981    /* xml: prefix is not really a namespace */
2982    if ((cur[0] == 'x') && (cur[1] == 'm') &&
2983        (cur[2] == 'l') && (cur[3] == ':'))
2984	return(xmlStrdup(name));
2985#endif
2986
2987    /* nasty but well=formed */
2988    if (cur[0] == ':')
2989	return(xmlStrdup(name));
2990
2991    c = *cur++;
2992    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2993	buf[len++] = c;
2994	c = *cur++;
2995    }
2996    if (len >= max) {
2997	/*
2998	 * Okay someone managed to make a huge name, so he's ready to pay
2999	 * for the processing speed.
3000	 */
3001	max = len * 2;
3002
3003	buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3004	if (buffer == NULL) {
3005	    xmlErrMemory(ctxt, NULL);
3006	    return(NULL);
3007	}
3008	memcpy(buffer, buf, len);
3009	while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3010	    if (len + 10 > max) {
3011	        xmlChar *tmp;
3012
3013		max *= 2;
3014		tmp = (xmlChar *) xmlRealloc(buffer,
3015						max * sizeof(xmlChar));
3016		if (tmp == NULL) {
3017		    xmlFree(buffer);
3018		    xmlErrMemory(ctxt, NULL);
3019		    return(NULL);
3020		}
3021		buffer = tmp;
3022	    }
3023	    buffer[len++] = c;
3024	    c = *cur++;
3025	}
3026	buffer[len] = 0;
3027    }
3028
3029    if ((c == ':') && (*cur == 0)) {
3030        if (buffer != NULL)
3031	    xmlFree(buffer);
3032	*prefix = NULL;
3033	return(xmlStrdup(name));
3034    }
3035
3036    if (buffer == NULL)
3037	ret = xmlStrndup(buf, len);
3038    else {
3039	ret = buffer;
3040	buffer = NULL;
3041	max = XML_MAX_NAMELEN;
3042    }
3043
3044
3045    if (c == ':') {
3046	c = *cur;
3047        *prefix = ret;
3048	if (c == 0) {
3049	    return(xmlStrndup(BAD_CAST "", 0));
3050	}
3051	len = 0;
3052
3053	/*
3054	 * Check that the first character is proper to start
3055	 * a new name
3056	 */
3057	if (!(((c >= 0x61) && (c <= 0x7A)) ||
3058	      ((c >= 0x41) && (c <= 0x5A)) ||
3059	      (c == '_') || (c == ':'))) {
3060	    int l;
3061	    int first = CUR_SCHAR(cur, l);
3062
3063	    if (!IS_LETTER(first) && (first != '_')) {
3064		xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3065			    "Name %s is not XML Namespace compliant\n",
3066				  name);
3067	    }
3068	}
3069	cur++;
3070
3071	while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3072	    buf[len++] = c;
3073	    c = *cur++;
3074	}
3075	if (len >= max) {
3076	    /*
3077	     * Okay someone managed to make a huge name, so he's ready to pay
3078	     * for the processing speed.
3079	     */
3080	    max = len * 2;
3081
3082	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3083	    if (buffer == NULL) {
3084	        xmlErrMemory(ctxt, NULL);
3085		return(NULL);
3086	    }
3087	    memcpy(buffer, buf, len);
3088	    while (c != 0) { /* tested bigname2.xml */
3089		if (len + 10 > max) {
3090		    xmlChar *tmp;
3091
3092		    max *= 2;
3093		    tmp = (xmlChar *) xmlRealloc(buffer,
3094						    max * sizeof(xmlChar));
3095		    if (tmp == NULL) {
3096			xmlErrMemory(ctxt, NULL);
3097			xmlFree(buffer);
3098			return(NULL);
3099		    }
3100		    buffer = tmp;
3101		}
3102		buffer[len++] = c;
3103		c = *cur++;
3104	    }
3105	    buffer[len] = 0;
3106	}
3107
3108	if (buffer == NULL)
3109	    ret = xmlStrndup(buf, len);
3110	else {
3111	    ret = buffer;
3112	}
3113    }
3114
3115    return(ret);
3116}
3117
3118/************************************************************************
3119 *									*
3120 *			The parser itself				*
3121 *	Relates to http://www.w3.org/TR/REC-xml				*
3122 *									*
3123 ************************************************************************/
3124
3125/************************************************************************
3126 *									*
3127 *	Routines to parse Name, NCName and NmToken			*
3128 *									*
3129 ************************************************************************/
3130#ifdef DEBUG
3131static unsigned long nbParseName = 0;
3132static unsigned long nbParseNmToken = 0;
3133static unsigned long nbParseNCName = 0;
3134static unsigned long nbParseNCNameComplex = 0;
3135static unsigned long nbParseNameComplex = 0;
3136static unsigned long nbParseStringName = 0;
3137#endif
3138
3139/*
3140 * The two following functions are related to the change of accepted
3141 * characters for Name and NmToken in the Revision 5 of XML-1.0
3142 * They correspond to the modified production [4] and the new production [4a]
3143 * changes in that revision. Also note that the macros used for the
3144 * productions Letter, Digit, CombiningChar and Extender are not needed
3145 * anymore.
3146 * We still keep compatibility to pre-revision5 parsing semantic if the
3147 * new XML_PARSE_OLD10 option is given to the parser.
3148 */
3149static int
3150xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3151    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3152        /*
3153	 * Use the new checks of production [4] [4a] amd [5] of the
3154	 * Update 5 of XML-1.0
3155	 */
3156	if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3157	    (((c >= 'a') && (c <= 'z')) ||
3158	     ((c >= 'A') && (c <= 'Z')) ||
3159	     (c == '_') || (c == ':') ||
3160	     ((c >= 0xC0) && (c <= 0xD6)) ||
3161	     ((c >= 0xD8) && (c <= 0xF6)) ||
3162	     ((c >= 0xF8) && (c <= 0x2FF)) ||
3163	     ((c >= 0x370) && (c <= 0x37D)) ||
3164	     ((c >= 0x37F) && (c <= 0x1FFF)) ||
3165	     ((c >= 0x200C) && (c <= 0x200D)) ||
3166	     ((c >= 0x2070) && (c <= 0x218F)) ||
3167	     ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3168	     ((c >= 0x3001) && (c <= 0xD7FF)) ||
3169	     ((c >= 0xF900) && (c <= 0xFDCF)) ||
3170	     ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3171	     ((c >= 0x10000) && (c <= 0xEFFFF))))
3172	    return(1);
3173    } else {
3174        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3175	    return(1);
3176    }
3177    return(0);
3178}
3179
3180static int
3181xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3182    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3183        /*
3184	 * Use the new checks of production [4] [4a] amd [5] of the
3185	 * Update 5 of XML-1.0
3186	 */
3187	if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3188	    (((c >= 'a') && (c <= 'z')) ||
3189	     ((c >= 'A') && (c <= 'Z')) ||
3190	     ((c >= '0') && (c <= '9')) || /* !start */
3191	     (c == '_') || (c == ':') ||
3192	     (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3193	     ((c >= 0xC0) && (c <= 0xD6)) ||
3194	     ((c >= 0xD8) && (c <= 0xF6)) ||
3195	     ((c >= 0xF8) && (c <= 0x2FF)) ||
3196	     ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3197	     ((c >= 0x370) && (c <= 0x37D)) ||
3198	     ((c >= 0x37F) && (c <= 0x1FFF)) ||
3199	     ((c >= 0x200C) && (c <= 0x200D)) ||
3200	     ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3201	     ((c >= 0x2070) && (c <= 0x218F)) ||
3202	     ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3203	     ((c >= 0x3001) && (c <= 0xD7FF)) ||
3204	     ((c >= 0xF900) && (c <= 0xFDCF)) ||
3205	     ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3206	     ((c >= 0x10000) && (c <= 0xEFFFF))))
3207	     return(1);
3208    } else {
3209        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3210            (c == '.') || (c == '-') ||
3211	    (c == '_') || (c == ':') ||
3212	    (IS_COMBINING(c)) ||
3213	    (IS_EXTENDER(c)))
3214	    return(1);
3215    }
3216    return(0);
3217}
3218
3219static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3220                                          int *len, int *alloc, int normalize);
3221
3222static const xmlChar *
3223xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3224    int len = 0, l;
3225    int c;
3226    int count = 0;
3227
3228#ifdef DEBUG
3229    nbParseNameComplex++;
3230#endif
3231
3232    /*
3233     * Handler for more complex cases
3234     */
3235    GROW;
3236    if (ctxt->instate == XML_PARSER_EOF)
3237        return(NULL);
3238    c = CUR_CHAR(l);
3239    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3240        /*
3241	 * Use the new checks of production [4] [4a] amd [5] of the
3242	 * Update 5 of XML-1.0
3243	 */
3244	if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3245	    (!(((c >= 'a') && (c <= 'z')) ||
3246	       ((c >= 'A') && (c <= 'Z')) ||
3247	       (c == '_') || (c == ':') ||
3248	       ((c >= 0xC0) && (c <= 0xD6)) ||
3249	       ((c >= 0xD8) && (c <= 0xF6)) ||
3250	       ((c >= 0xF8) && (c <= 0x2FF)) ||
3251	       ((c >= 0x370) && (c <= 0x37D)) ||
3252	       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3253	       ((c >= 0x200C) && (c <= 0x200D)) ||
3254	       ((c >= 0x2070) && (c <= 0x218F)) ||
3255	       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3256	       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3257	       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3258	       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3259	       ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3260	    return(NULL);
3261	}
3262	len += l;
3263	NEXTL(l);
3264	c = CUR_CHAR(l);
3265	while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3266	       (((c >= 'a') && (c <= 'z')) ||
3267	        ((c >= 'A') && (c <= 'Z')) ||
3268	        ((c >= '0') && (c <= '9')) || /* !start */
3269	        (c == '_') || (c == ':') ||
3270	        (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3271	        ((c >= 0xC0) && (c <= 0xD6)) ||
3272	        ((c >= 0xD8) && (c <= 0xF6)) ||
3273	        ((c >= 0xF8) && (c <= 0x2FF)) ||
3274	        ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3275	        ((c >= 0x370) && (c <= 0x37D)) ||
3276	        ((c >= 0x37F) && (c <= 0x1FFF)) ||
3277	        ((c >= 0x200C) && (c <= 0x200D)) ||
3278	        ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3279	        ((c >= 0x2070) && (c <= 0x218F)) ||
3280	        ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3281	        ((c >= 0x3001) && (c <= 0xD7FF)) ||
3282	        ((c >= 0xF900) && (c <= 0xFDCF)) ||
3283	        ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3284	        ((c >= 0x10000) && (c <= 0xEFFFF))
3285		)) {
3286	    if (count++ > XML_PARSER_CHUNK_SIZE) {
3287		count = 0;
3288		GROW;
3289                if (ctxt->instate == XML_PARSER_EOF)
3290                    return(NULL);
3291	    }
3292	    len += l;
3293	    NEXTL(l);
3294	    c = CUR_CHAR(l);
3295	}
3296    } else {
3297	if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3298	    (!IS_LETTER(c) && (c != '_') &&
3299	     (c != ':'))) {
3300	    return(NULL);
3301	}
3302	len += l;
3303	NEXTL(l);
3304	c = CUR_CHAR(l);
3305
3306	while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3307	       ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3308		(c == '.') || (c == '-') ||
3309		(c == '_') || (c == ':') ||
3310		(IS_COMBINING(c)) ||
3311		(IS_EXTENDER(c)))) {
3312	    if (count++ > XML_PARSER_CHUNK_SIZE) {
3313		count = 0;
3314		GROW;
3315                if (ctxt->instate == XML_PARSER_EOF)
3316                    return(NULL);
3317	    }
3318	    len += l;
3319	    NEXTL(l);
3320	    c = CUR_CHAR(l);
3321	    if (c == 0) {
3322		count = 0;
3323		GROW;
3324                if (ctxt->instate == XML_PARSER_EOF)
3325                    return(NULL);
3326		c = CUR_CHAR(l);
3327	    }
3328	}
3329    }
3330    if ((len > XML_MAX_NAME_LENGTH) &&
3331        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3332        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3333        return(NULL);
3334    }
3335    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3336        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3337    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3338}
3339
3340/**
3341 * xmlParseName:
3342 * @ctxt:  an XML parser context
3343 *
3344 * parse an XML name.
3345 *
3346 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3347 *                  CombiningChar | Extender
3348 *
3349 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3350 *
3351 * [6] Names ::= Name (#x20 Name)*
3352 *
3353 * Returns the Name parsed or NULL
3354 */
3355
3356const xmlChar *
3357xmlParseName(xmlParserCtxtPtr ctxt) {
3358    const xmlChar *in;
3359    const xmlChar *ret;
3360    int count = 0;
3361
3362    GROW;
3363
3364#ifdef DEBUG
3365    nbParseName++;
3366#endif
3367
3368    /*
3369     * Accelerator for simple ASCII names
3370     */
3371    in = ctxt->input->cur;
3372    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3373	((*in >= 0x41) && (*in <= 0x5A)) ||
3374	(*in == '_') || (*in == ':')) {
3375	in++;
3376	while (((*in >= 0x61) && (*in <= 0x7A)) ||
3377	       ((*in >= 0x41) && (*in <= 0x5A)) ||
3378	       ((*in >= 0x30) && (*in <= 0x39)) ||
3379	       (*in == '_') || (*in == '-') ||
3380	       (*in == ':') || (*in == '.'))
3381	    in++;
3382	if ((*in > 0) && (*in < 0x80)) {
3383	    count = in - ctxt->input->cur;
3384            if ((count > XML_MAX_NAME_LENGTH) &&
3385                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3386                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3387                return(NULL);
3388            }
3389	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3390	    ctxt->input->cur = in;
3391	    ctxt->nbChars += count;
3392	    ctxt->input->col += count;
3393	    if (ret == NULL)
3394	        xmlErrMemory(ctxt, NULL);
3395	    return(ret);
3396	}
3397    }
3398    /* accelerator for special cases */
3399    return(xmlParseNameComplex(ctxt));
3400}
3401
3402static const xmlChar *
3403xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3404    int len = 0, l;
3405    int c;
3406    int count = 0;
3407
3408#ifdef DEBUG
3409    nbParseNCNameComplex++;
3410#endif
3411
3412    /*
3413     * Handler for more complex cases
3414     */
3415    GROW;
3416    c = CUR_CHAR(l);
3417    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3418	(!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3419	return(NULL);
3420    }
3421
3422    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3423	   (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3424	if (count++ > XML_PARSER_CHUNK_SIZE) {
3425            if ((len > XML_MAX_NAME_LENGTH) &&
3426                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3427                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3428                return(NULL);
3429            }
3430	    count = 0;
3431	    GROW;
3432            if (ctxt->instate == XML_PARSER_EOF)
3433                return(NULL);
3434	}
3435	len += l;
3436	NEXTL(l);
3437	c = CUR_CHAR(l);
3438	if (c == 0) {
3439	    count = 0;
3440	    GROW;
3441            if (ctxt->instate == XML_PARSER_EOF)
3442                return(NULL);
3443	    c = CUR_CHAR(l);
3444	}
3445    }
3446    if ((len > XML_MAX_NAME_LENGTH) &&
3447        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3448        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3449        return(NULL);
3450    }
3451    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3452}
3453
3454/**
3455 * xmlParseNCName:
3456 * @ctxt:  an XML parser context
3457 * @len:  length of the string parsed
3458 *
3459 * parse an XML name.
3460 *
3461 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3462 *                      CombiningChar | Extender
3463 *
3464 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3465 *
3466 * Returns the Name parsed or NULL
3467 */
3468
3469static const xmlChar *
3470xmlParseNCName(xmlParserCtxtPtr ctxt) {
3471    const xmlChar *in;
3472    const xmlChar *ret;
3473    int count = 0;
3474
3475#ifdef DEBUG
3476    nbParseNCName++;
3477#endif
3478
3479    /*
3480     * Accelerator for simple ASCII names
3481     */
3482    in = ctxt->input->cur;
3483    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3484	((*in >= 0x41) && (*in <= 0x5A)) ||
3485	(*in == '_')) {
3486	in++;
3487	while (((*in >= 0x61) && (*in <= 0x7A)) ||
3488	       ((*in >= 0x41) && (*in <= 0x5A)) ||
3489	       ((*in >= 0x30) && (*in <= 0x39)) ||
3490	       (*in == '_') || (*in == '-') ||
3491	       (*in == '.'))
3492	    in++;
3493	if ((*in > 0) && (*in < 0x80)) {
3494	    count = in - ctxt->input->cur;
3495            if ((count > XML_MAX_NAME_LENGTH) &&
3496                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3497                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3498                return(NULL);
3499            }
3500	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3501	    ctxt->input->cur = in;
3502	    ctxt->nbChars += count;
3503	    ctxt->input->col += count;
3504	    if (ret == NULL) {
3505	        xmlErrMemory(ctxt, NULL);
3506	    }
3507	    return(ret);
3508	}
3509    }
3510    return(xmlParseNCNameComplex(ctxt));
3511}
3512
3513/**
3514 * xmlParseNameAndCompare:
3515 * @ctxt:  an XML parser context
3516 *
3517 * parse an XML name and compares for match
3518 * (specialized for endtag parsing)
3519 *
3520 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3521 * and the name for mismatch
3522 */
3523
3524static const xmlChar *
3525xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3526    register const xmlChar *cmp = other;
3527    register const xmlChar *in;
3528    const xmlChar *ret;
3529
3530    GROW;
3531    if (ctxt->instate == XML_PARSER_EOF)
3532        return(NULL);
3533
3534    in = ctxt->input->cur;
3535    while (*in != 0 && *in == *cmp) {
3536	++in;
3537	++cmp;
3538	ctxt->input->col++;
3539    }
3540    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3541	/* success */
3542	ctxt->input->cur = in;
3543	return (const xmlChar*) 1;
3544    }
3545    /* failure (or end of input buffer), check with full function */
3546    ret = xmlParseName (ctxt);
3547    /* strings coming from the dictionnary direct compare possible */
3548    if (ret == other) {
3549	return (const xmlChar*) 1;
3550    }
3551    return ret;
3552}
3553
3554/**
3555 * xmlParseStringName:
3556 * @ctxt:  an XML parser context
3557 * @str:  a pointer to the string pointer (IN/OUT)
3558 *
3559 * parse an XML name.
3560 *
3561 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3562 *                  CombiningChar | Extender
3563 *
3564 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3565 *
3566 * [6] Names ::= Name (#x20 Name)*
3567 *
3568 * Returns the Name parsed or NULL. The @str pointer
3569 * is updated to the current location in the string.
3570 */
3571
3572static xmlChar *
3573xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3574    xmlChar buf[XML_MAX_NAMELEN + 5];
3575    const xmlChar *cur = *str;
3576    int len = 0, l;
3577    int c;
3578
3579#ifdef DEBUG
3580    nbParseStringName++;
3581#endif
3582
3583    c = CUR_SCHAR(cur, l);
3584    if (!xmlIsNameStartChar(ctxt, c)) {
3585	return(NULL);
3586    }
3587
3588    COPY_BUF(l,buf,len,c);
3589    cur += l;
3590    c = CUR_SCHAR(cur, l);
3591    while (xmlIsNameChar(ctxt, c)) {
3592	COPY_BUF(l,buf,len,c);
3593	cur += l;
3594	c = CUR_SCHAR(cur, l);
3595	if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3596	    /*
3597	     * Okay someone managed to make a huge name, so he's ready to pay
3598	     * for the processing speed.
3599	     */
3600	    xmlChar *buffer;
3601	    int max = len * 2;
3602
3603	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3604	    if (buffer == NULL) {
3605	        xmlErrMemory(ctxt, NULL);
3606		return(NULL);
3607	    }
3608	    memcpy(buffer, buf, len);
3609	    while (xmlIsNameChar(ctxt, c)) {
3610		if (len + 10 > max) {
3611		    xmlChar *tmp;
3612
3613                    if ((len > XML_MAX_NAME_LENGTH) &&
3614                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3615                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3616			xmlFree(buffer);
3617                        return(NULL);
3618                    }
3619		    max *= 2;
3620		    tmp = (xmlChar *) xmlRealloc(buffer,
3621			                            max * sizeof(xmlChar));
3622		    if (tmp == NULL) {
3623			xmlErrMemory(ctxt, NULL);
3624			xmlFree(buffer);
3625			return(NULL);
3626		    }
3627		    buffer = tmp;
3628		}
3629		COPY_BUF(l,buffer,len,c);
3630		cur += l;
3631		c = CUR_SCHAR(cur, l);
3632	    }
3633	    buffer[len] = 0;
3634	    *str = cur;
3635	    return(buffer);
3636	}
3637    }
3638    if ((len > XML_MAX_NAME_LENGTH) &&
3639        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3640        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3641        return(NULL);
3642    }
3643    *str = cur;
3644    return(xmlStrndup(buf, len));
3645}
3646
3647/**
3648 * xmlParseNmtoken:
3649 * @ctxt:  an XML parser context
3650 *
3651 * parse an XML Nmtoken.
3652 *
3653 * [7] Nmtoken ::= (NameChar)+
3654 *
3655 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3656 *
3657 * Returns the Nmtoken parsed or NULL
3658 */
3659
3660xmlChar *
3661xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3662    xmlChar buf[XML_MAX_NAMELEN + 5];
3663    int len = 0, l;
3664    int c;
3665    int count = 0;
3666
3667#ifdef DEBUG
3668    nbParseNmToken++;
3669#endif
3670
3671    GROW;
3672    if (ctxt->instate == XML_PARSER_EOF)
3673        return(NULL);
3674    c = CUR_CHAR(l);
3675
3676    while (xmlIsNameChar(ctxt, c)) {
3677	if (count++ > XML_PARSER_CHUNK_SIZE) {
3678	    count = 0;
3679	    GROW;
3680	}
3681	COPY_BUF(l,buf,len,c);
3682	NEXTL(l);
3683	c = CUR_CHAR(l);
3684	if (c == 0) {
3685	    count = 0;
3686	    GROW;
3687	    if (ctxt->instate == XML_PARSER_EOF)
3688		return(NULL);
3689            c = CUR_CHAR(l);
3690	}
3691	if (len >= XML_MAX_NAMELEN) {
3692	    /*
3693	     * Okay someone managed to make a huge token, so he's ready to pay
3694	     * for the processing speed.
3695	     */
3696	    xmlChar *buffer;
3697	    int max = len * 2;
3698
3699	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3700	    if (buffer == NULL) {
3701	        xmlErrMemory(ctxt, NULL);
3702		return(NULL);
3703	    }
3704	    memcpy(buffer, buf, len);
3705	    while (xmlIsNameChar(ctxt, c)) {
3706		if (count++ > XML_PARSER_CHUNK_SIZE) {
3707		    count = 0;
3708		    GROW;
3709                    if (ctxt->instate == XML_PARSER_EOF) {
3710                        xmlFree(buffer);
3711                        return(NULL);
3712                    }
3713		}
3714		if (len + 10 > max) {
3715		    xmlChar *tmp;
3716
3717                    if ((max > XML_MAX_NAME_LENGTH) &&
3718                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3719                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3720                        xmlFree(buffer);
3721                        return(NULL);
3722                    }
3723		    max *= 2;
3724		    tmp = (xmlChar *) xmlRealloc(buffer,
3725			                            max * sizeof(xmlChar));
3726		    if (tmp == NULL) {
3727			xmlErrMemory(ctxt, NULL);
3728			xmlFree(buffer);
3729			return(NULL);
3730		    }
3731		    buffer = tmp;
3732		}
3733		COPY_BUF(l,buffer,len,c);
3734		NEXTL(l);
3735		c = CUR_CHAR(l);
3736	    }
3737	    buffer[len] = 0;
3738	    return(buffer);
3739	}
3740    }
3741    if (len == 0)
3742        return(NULL);
3743    if ((len > XML_MAX_NAME_LENGTH) &&
3744        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3745        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3746        return(NULL);
3747    }
3748    return(xmlStrndup(buf, len));
3749}
3750
3751/**
3752 * xmlParseEntityValue:
3753 * @ctxt:  an XML parser context
3754 * @orig:  if non-NULL store a copy of the original entity value
3755 *
3756 * parse a value for ENTITY declarations
3757 *
3758 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3759 *	               "'" ([^%&'] | PEReference | Reference)* "'"
3760 *
3761 * Returns the EntityValue parsed with reference substituted or NULL
3762 */
3763
3764xmlChar *
3765xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3766    xmlChar *buf = NULL;
3767    int len = 0;
3768    int size = XML_PARSER_BUFFER_SIZE;
3769    int c, l;
3770    xmlChar stop;
3771    xmlChar *ret = NULL;
3772    const xmlChar *cur = NULL;
3773    xmlParserInputPtr input;
3774
3775    if (RAW == '"') stop = '"';
3776    else if (RAW == '\'') stop = '\'';
3777    else {
3778	xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3779	return(NULL);
3780    }
3781    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3782    if (buf == NULL) {
3783	xmlErrMemory(ctxt, NULL);
3784	return(NULL);
3785    }
3786
3787    /*
3788     * The content of the entity definition is copied in a buffer.
3789     */
3790
3791    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3792    input = ctxt->input;
3793    GROW;
3794    if (ctxt->instate == XML_PARSER_EOF) {
3795        xmlFree(buf);
3796        return(NULL);
3797    }
3798    NEXT;
3799    c = CUR_CHAR(l);
3800    /*
3801     * NOTE: 4.4.5 Included in Literal
3802     * When a parameter entity reference appears in a literal entity
3803     * value, ... a single or double quote character in the replacement
3804     * text is always treated as a normal data character and will not
3805     * terminate the literal.
3806     * In practice it means we stop the loop only when back at parsing
3807     * the initial entity and the quote is found
3808     */
3809    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3810	    (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3811	if (len + 5 >= size) {
3812	    xmlChar *tmp;
3813
3814	    size *= 2;
3815	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
3816	    if (tmp == NULL) {
3817		xmlErrMemory(ctxt, NULL);
3818		xmlFree(buf);
3819		return(NULL);
3820	    }
3821	    buf = tmp;
3822	}
3823	COPY_BUF(l,buf,len,c);
3824	NEXTL(l);
3825	/*
3826	 * Pop-up of finished entities.
3827	 */
3828	while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
3829	    xmlPopInput(ctxt);
3830
3831	GROW;
3832	c = CUR_CHAR(l);
3833	if (c == 0) {
3834	    GROW;
3835	    c = CUR_CHAR(l);
3836	}
3837    }
3838    buf[len] = 0;
3839    if (ctxt->instate == XML_PARSER_EOF) {
3840        xmlFree(buf);
3841        return(NULL);
3842    }
3843
3844    /*
3845     * Raise problem w.r.t. '&' and '%' being used in non-entities
3846     * reference constructs. Note Charref will be handled in
3847     * xmlStringDecodeEntities()
3848     */
3849    cur = buf;
3850    while (*cur != 0) { /* non input consuming */
3851	if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3852	    xmlChar *name;
3853	    xmlChar tmp = *cur;
3854
3855	    cur++;
3856	    name = xmlParseStringName(ctxt, &cur);
3857            if ((name == NULL) || (*cur != ';')) {
3858		xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3859	    "EntityValue: '%c' forbidden except for entities references\n",
3860	                          tmp);
3861	    }
3862	    if ((tmp == '%') && (ctxt->inSubset == 1) &&
3863		(ctxt->inputNr == 1)) {
3864		xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3865	    }
3866	    if (name != NULL)
3867		xmlFree(name);
3868	    if (*cur == 0)
3869	        break;
3870	}
3871	cur++;
3872    }
3873
3874    /*
3875     * Then PEReference entities are substituted.
3876     */
3877    if (c != stop) {
3878	xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3879	xmlFree(buf);
3880    } else {
3881	NEXT;
3882	/*
3883	 * NOTE: 4.4.7 Bypassed
3884	 * When a general entity reference appears in the EntityValue in
3885	 * an entity declaration, it is bypassed and left as is.
3886	 * so XML_SUBSTITUTE_REF is not set here.
3887	 */
3888	ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3889				      0, 0, 0);
3890	if (orig != NULL)
3891	    *orig = buf;
3892	else
3893	    xmlFree(buf);
3894    }
3895
3896    return(ret);
3897}
3898
3899/**
3900 * xmlParseAttValueComplex:
3901 * @ctxt:  an XML parser context
3902 * @len:   the resulting attribute len
3903 * @normalize:  wether to apply the inner normalization
3904 *
3905 * parse a value for an attribute, this is the fallback function
3906 * of xmlParseAttValue() when the attribute parsing requires handling
3907 * of non-ASCII characters, or normalization compaction.
3908 *
3909 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3910 */
3911static xmlChar *
3912xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3913    xmlChar limit = 0;
3914    xmlChar *buf = NULL;
3915    xmlChar *rep = NULL;
3916    size_t len = 0;
3917    size_t buf_size = 0;
3918    int c, l, in_space = 0;
3919    xmlChar *current = NULL;
3920    xmlEntityPtr ent;
3921
3922    if (NXT(0) == '"') {
3923	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3924	limit = '"';
3925        NEXT;
3926    } else if (NXT(0) == '\'') {
3927	limit = '\'';
3928	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3929        NEXT;
3930    } else {
3931	xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3932	return(NULL);
3933    }
3934
3935    /*
3936     * allocate a translation buffer.
3937     */
3938    buf_size = XML_PARSER_BUFFER_SIZE;
3939    buf = (xmlChar *) xmlMallocAtomic(buf_size);
3940    if (buf == NULL) goto mem_error;
3941
3942    /*
3943     * OK loop until we reach one of the ending char or a size limit.
3944     */
3945    c = CUR_CHAR(l);
3946    while (((NXT(0) != limit) && /* checked */
3947            (IS_CHAR(c)) && (c != '<')) &&
3948            (ctxt->instate != XML_PARSER_EOF)) {
3949        /*
3950         * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
3951         * special option is given
3952         */
3953        if ((len > XML_MAX_TEXT_LENGTH) &&
3954            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3955            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
3956                           "AttValue length too long\n");
3957            goto mem_error;
3958        }
3959	if (c == 0) break;
3960	if (c == '&') {
3961	    in_space = 0;
3962	    if (NXT(1) == '#') {
3963		int val = xmlParseCharRef(ctxt);
3964
3965		if (val == '&') {
3966		    if (ctxt->replaceEntities) {
3967			if (len + 10 > buf_size) {
3968			    growBuffer(buf, 10);
3969			}
3970			buf[len++] = '&';
3971		    } else {
3972			/*
3973			 * The reparsing will be done in xmlStringGetNodeList()
3974			 * called by the attribute() function in SAX.c
3975			 */
3976			if (len + 10 > buf_size) {
3977			    growBuffer(buf, 10);
3978			}
3979			buf[len++] = '&';
3980			buf[len++] = '#';
3981			buf[len++] = '3';
3982			buf[len++] = '8';
3983			buf[len++] = ';';
3984		    }
3985		} else if (val != 0) {
3986		    if (len + 10 > buf_size) {
3987			growBuffer(buf, 10);
3988		    }
3989		    len += xmlCopyChar(0, &buf[len], val);
3990		}
3991	    } else {
3992		ent = xmlParseEntityRef(ctxt);
3993		ctxt->nbentities++;
3994		if (ent != NULL)
3995		    ctxt->nbentities += ent->owner;
3996		if ((ent != NULL) &&
3997		    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
3998		    if (len + 10 > buf_size) {
3999			growBuffer(buf, 10);
4000		    }
4001		    if ((ctxt->replaceEntities == 0) &&
4002		        (ent->content[0] == '&')) {
4003			buf[len++] = '&';
4004			buf[len++] = '#';
4005			buf[len++] = '3';
4006			buf[len++] = '8';
4007			buf[len++] = ';';
4008		    } else {
4009			buf[len++] = ent->content[0];
4010		    }
4011		} else if ((ent != NULL) &&
4012		           (ctxt->replaceEntities != 0)) {
4013		    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4014			rep = xmlStringDecodeEntities(ctxt, ent->content,
4015						      XML_SUBSTITUTE_REF,
4016						      0, 0, 0);
4017			if (rep != NULL) {
4018			    current = rep;
4019			    while (*current != 0) { /* non input consuming */
4020                                if ((*current == 0xD) || (*current == 0xA) ||
4021                                    (*current == 0x9)) {
4022                                    buf[len++] = 0x20;
4023                                    current++;
4024                                } else
4025                                    buf[len++] = *current++;
4026				if (len + 10 > buf_size) {
4027				    growBuffer(buf, 10);
4028				}
4029			    }
4030			    xmlFree(rep);
4031			    rep = NULL;
4032			}
4033		    } else {
4034			if (len + 10 > buf_size) {
4035			    growBuffer(buf, 10);
4036			}
4037			if (ent->content != NULL)
4038			    buf[len++] = ent->content[0];
4039		    }
4040		} else if (ent != NULL) {
4041		    int i = xmlStrlen(ent->name);
4042		    const xmlChar *cur = ent->name;
4043
4044		    /*
4045		     * This may look absurd but is needed to detect
4046		     * entities problems
4047		     */
4048		    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4049			(ent->content != NULL) && (ent->checked == 0)) {
4050			unsigned long oldnbent = ctxt->nbentities;
4051
4052			rep = xmlStringDecodeEntities(ctxt, ent->content,
4053						  XML_SUBSTITUTE_REF, 0, 0, 0);
4054
4055			ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
4056			if (rep != NULL) {
4057			    if (xmlStrchr(rep, '<'))
4058			        ent->checked |= 1;
4059			    xmlFree(rep);
4060			    rep = NULL;
4061			}
4062		    }
4063
4064		    /*
4065		     * Just output the reference
4066		     */
4067		    buf[len++] = '&';
4068		    while (len + i + 10 > buf_size) {
4069			growBuffer(buf, i + 10);
4070		    }
4071		    for (;i > 0;i--)
4072			buf[len++] = *cur++;
4073		    buf[len++] = ';';
4074		}
4075	    }
4076	} else {
4077	    if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4078	        if ((len != 0) || (!normalize)) {
4079		    if ((!normalize) || (!in_space)) {
4080			COPY_BUF(l,buf,len,0x20);
4081			while (len + 10 > buf_size) {
4082			    growBuffer(buf, 10);
4083			}
4084		    }
4085		    in_space = 1;
4086		}
4087	    } else {
4088	        in_space = 0;
4089		COPY_BUF(l,buf,len,c);
4090		if (len + 10 > buf_size) {
4091		    growBuffer(buf, 10);
4092		}
4093	    }
4094	    NEXTL(l);
4095	}
4096	GROW;
4097	c = CUR_CHAR(l);
4098    }
4099    if (ctxt->instate == XML_PARSER_EOF)
4100        goto error;
4101
4102    if ((in_space) && (normalize)) {
4103        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4104    }
4105    buf[len] = 0;
4106    if (RAW == '<') {
4107	xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4108    } else if (RAW != limit) {
4109	if ((c != 0) && (!IS_CHAR(c))) {
4110	    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4111			   "invalid character in attribute value\n");
4112	} else {
4113	    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4114			   "AttValue: ' expected\n");
4115        }
4116    } else
4117	NEXT;
4118
4119    /*
4120     * There we potentially risk an overflow, don't allow attribute value of
4121     * length more than INT_MAX it is a very reasonnable assumption !
4122     */
4123    if (len >= INT_MAX) {
4124        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4125                       "AttValue length too long\n");
4126        goto mem_error;
4127    }
4128
4129    if (attlen != NULL) *attlen = (int) len;
4130    return(buf);
4131
4132mem_error:
4133    xmlErrMemory(ctxt, NULL);
4134error:
4135    if (buf != NULL)
4136        xmlFree(buf);
4137    if (rep != NULL)
4138        xmlFree(rep);
4139    return(NULL);
4140}
4141
4142/**
4143 * xmlParseAttValue:
4144 * @ctxt:  an XML parser context
4145 *
4146 * parse a value for an attribute
4147 * Note: the parser won't do substitution of entities here, this
4148 * will be handled later in xmlStringGetNodeList
4149 *
4150 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4151 *                   "'" ([^<&'] | Reference)* "'"
4152 *
4153 * 3.3.3 Attribute-Value Normalization:
4154 * Before the value of an attribute is passed to the application or
4155 * checked for validity, the XML processor must normalize it as follows:
4156 * - a character reference is processed by appending the referenced
4157 *   character to the attribute value
4158 * - an entity reference is processed by recursively processing the
4159 *   replacement text of the entity
4160 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4161 *   appending #x20 to the normalized value, except that only a single
4162 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4163 *   parsed entity or the literal entity value of an internal parsed entity
4164 * - other characters are processed by appending them to the normalized value
4165 * If the declared value is not CDATA, then the XML processor must further
4166 * process the normalized attribute value by discarding any leading and
4167 * trailing space (#x20) characters, and by replacing sequences of space
4168 * (#x20) characters by a single space (#x20) character.
4169 * All attributes for which no declaration has been read should be treated
4170 * by a non-validating parser as if declared CDATA.
4171 *
4172 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4173 */
4174
4175
4176xmlChar *
4177xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4178    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4179    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4180}
4181
4182/**
4183 * xmlParseSystemLiteral:
4184 * @ctxt:  an XML parser context
4185 *
4186 * parse an XML Literal
4187 *
4188 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4189 *
4190 * Returns the SystemLiteral parsed or NULL
4191 */
4192
4193xmlChar *
4194xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4195    xmlChar *buf = NULL;
4196    int len = 0;
4197    int size = XML_PARSER_BUFFER_SIZE;
4198    int cur, l;
4199    xmlChar stop;
4200    int state = ctxt->instate;
4201    int count = 0;
4202
4203    SHRINK;
4204    if (RAW == '"') {
4205        NEXT;
4206	stop = '"';
4207    } else if (RAW == '\'') {
4208        NEXT;
4209	stop = '\'';
4210    } else {
4211	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4212	return(NULL);
4213    }
4214
4215    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4216    if (buf == NULL) {
4217        xmlErrMemory(ctxt, NULL);
4218	return(NULL);
4219    }
4220    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4221    cur = CUR_CHAR(l);
4222    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4223	if (len + 5 >= size) {
4224	    xmlChar *tmp;
4225
4226            if ((size > XML_MAX_NAME_LENGTH) &&
4227                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4228                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4229                xmlFree(buf);
4230		ctxt->instate = (xmlParserInputState) state;
4231                return(NULL);
4232            }
4233	    size *= 2;
4234	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4235	    if (tmp == NULL) {
4236	        xmlFree(buf);
4237		xmlErrMemory(ctxt, NULL);
4238		ctxt->instate = (xmlParserInputState) state;
4239		return(NULL);
4240	    }
4241	    buf = tmp;
4242	}
4243	count++;
4244	if (count > 50) {
4245	    GROW;
4246	    count = 0;
4247            if (ctxt->instate == XML_PARSER_EOF) {
4248	        xmlFree(buf);
4249		return(NULL);
4250            }
4251	}
4252	COPY_BUF(l,buf,len,cur);
4253	NEXTL(l);
4254	cur = CUR_CHAR(l);
4255	if (cur == 0) {
4256	    GROW;
4257	    SHRINK;
4258	    cur = CUR_CHAR(l);
4259	}
4260    }
4261    buf[len] = 0;
4262    ctxt->instate = (xmlParserInputState) state;
4263    if (!IS_CHAR(cur)) {
4264	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4265    } else {
4266	NEXT;
4267    }
4268    return(buf);
4269}
4270
4271/**
4272 * xmlParsePubidLiteral:
4273 * @ctxt:  an XML parser context
4274 *
4275 * parse an XML public literal
4276 *
4277 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4278 *
4279 * Returns the PubidLiteral parsed or NULL.
4280 */
4281
4282xmlChar *
4283xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4284    xmlChar *buf = NULL;
4285    int len = 0;
4286    int size = XML_PARSER_BUFFER_SIZE;
4287    xmlChar cur;
4288    xmlChar stop;
4289    int count = 0;
4290    xmlParserInputState oldstate = ctxt->instate;
4291
4292    SHRINK;
4293    if (RAW == '"') {
4294        NEXT;
4295	stop = '"';
4296    } else if (RAW == '\'') {
4297        NEXT;
4298	stop = '\'';
4299    } else {
4300	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4301	return(NULL);
4302    }
4303    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4304    if (buf == NULL) {
4305	xmlErrMemory(ctxt, NULL);
4306	return(NULL);
4307    }
4308    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4309    cur = CUR;
4310    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4311	if (len + 1 >= size) {
4312	    xmlChar *tmp;
4313
4314            if ((size > XML_MAX_NAME_LENGTH) &&
4315                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4316                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4317                xmlFree(buf);
4318                return(NULL);
4319            }
4320	    size *= 2;
4321	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4322	    if (tmp == NULL) {
4323		xmlErrMemory(ctxt, NULL);
4324		xmlFree(buf);
4325		return(NULL);
4326	    }
4327	    buf = tmp;
4328	}
4329	buf[len++] = cur;
4330	count++;
4331	if (count > 50) {
4332	    GROW;
4333	    count = 0;
4334            if (ctxt->instate == XML_PARSER_EOF) {
4335		xmlFree(buf);
4336		return(NULL);
4337            }
4338	}
4339	NEXT;
4340	cur = CUR;
4341	if (cur == 0) {
4342	    GROW;
4343	    SHRINK;
4344	    cur = CUR;
4345	}
4346    }
4347    buf[len] = 0;
4348    if (cur != stop) {
4349	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4350    } else {
4351	NEXT;
4352    }
4353    ctxt->instate = oldstate;
4354    return(buf);
4355}
4356
4357static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
4358
4359/*
4360 * used for the test in the inner loop of the char data testing
4361 */
4362static const unsigned char test_char_data[256] = {
4363    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4364    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4365    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4366    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4367    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4368    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4369    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4370    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4371    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4372    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4373    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4374    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4375    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4376    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4377    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4378    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4379    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4380    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4381    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4382    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4383    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4384    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4385    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4386    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4387    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4388    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4389    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4390    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4391    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4392    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4393    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4394    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4395};
4396
4397/**
4398 * xmlParseCharData:
4399 * @ctxt:  an XML parser context
4400 * @cdata:  int indicating whether we are within a CDATA section
4401 *
4402 * parse a CharData section.
4403 * if we are within a CDATA section ']]>' marks an end of section.
4404 *
4405 * The right angle bracket (>) may be represented using the string "&gt;",
4406 * and must, for compatibility, be escaped using "&gt;" or a character
4407 * reference when it appears in the string "]]>" in content, when that
4408 * string is not marking the end of a CDATA section.
4409 *
4410 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4411 */
4412
4413void
4414xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
4415    const xmlChar *in;
4416    int nbchar = 0;
4417    int line = ctxt->input->line;
4418    int col = ctxt->input->col;
4419    int ccol;
4420
4421    SHRINK;
4422    GROW;
4423    /*
4424     * Accelerated common case where input don't need to be
4425     * modified before passing it to the handler.
4426     */
4427    if (!cdata) {
4428	in = ctxt->input->cur;
4429	do {
4430get_more_space:
4431	    while (*in == 0x20) { in++; ctxt->input->col++; }
4432	    if (*in == 0xA) {
4433		do {
4434		    ctxt->input->line++; ctxt->input->col = 1;
4435		    in++;
4436		} while (*in == 0xA);
4437		goto get_more_space;
4438	    }
4439	    if (*in == '<') {
4440		nbchar = in - ctxt->input->cur;
4441		if (nbchar > 0) {
4442		    const xmlChar *tmp = ctxt->input->cur;
4443		    ctxt->input->cur = in;
4444
4445		    if ((ctxt->sax != NULL) &&
4446		        (ctxt->sax->ignorableWhitespace !=
4447		         ctxt->sax->characters)) {
4448			if (areBlanks(ctxt, tmp, nbchar, 1)) {
4449			    if (ctxt->sax->ignorableWhitespace != NULL)
4450				ctxt->sax->ignorableWhitespace(ctxt->userData,
4451						       tmp, nbchar);
4452			} else {
4453			    if (ctxt->sax->characters != NULL)
4454				ctxt->sax->characters(ctxt->userData,
4455						      tmp, nbchar);
4456			    if (*ctxt->space == -1)
4457			        *ctxt->space = -2;
4458			}
4459		    } else if ((ctxt->sax != NULL) &&
4460		               (ctxt->sax->characters != NULL)) {
4461			ctxt->sax->characters(ctxt->userData,
4462					      tmp, nbchar);
4463		    }
4464		}
4465		return;
4466	    }
4467
4468get_more:
4469            ccol = ctxt->input->col;
4470	    while (test_char_data[*in]) {
4471		in++;
4472		ccol++;
4473	    }
4474	    ctxt->input->col = ccol;
4475	    if (*in == 0xA) {
4476		do {
4477		    ctxt->input->line++; ctxt->input->col = 1;
4478		    in++;
4479		} while (*in == 0xA);
4480		goto get_more;
4481	    }
4482	    if (*in == ']') {
4483		if ((in[1] == ']') && (in[2] == '>')) {
4484		    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4485		    ctxt->input->cur = in;
4486		    return;
4487		}
4488		in++;
4489		ctxt->input->col++;
4490		goto get_more;
4491	    }
4492	    nbchar = in - ctxt->input->cur;
4493	    if (nbchar > 0) {
4494		if ((ctxt->sax != NULL) &&
4495		    (ctxt->sax->ignorableWhitespace !=
4496		     ctxt->sax->characters) &&
4497		    (IS_BLANK_CH(*ctxt->input->cur))) {
4498		    const xmlChar *tmp = ctxt->input->cur;
4499		    ctxt->input->cur = in;
4500
4501		    if (areBlanks(ctxt, tmp, nbchar, 0)) {
4502		        if (ctxt->sax->ignorableWhitespace != NULL)
4503			    ctxt->sax->ignorableWhitespace(ctxt->userData,
4504							   tmp, nbchar);
4505		    } else {
4506		        if (ctxt->sax->characters != NULL)
4507			    ctxt->sax->characters(ctxt->userData,
4508						  tmp, nbchar);
4509			if (*ctxt->space == -1)
4510			    *ctxt->space = -2;
4511		    }
4512                    line = ctxt->input->line;
4513                    col = ctxt->input->col;
4514		} else if (ctxt->sax != NULL) {
4515		    if (ctxt->sax->characters != NULL)
4516			ctxt->sax->characters(ctxt->userData,
4517					      ctxt->input->cur, nbchar);
4518                    line = ctxt->input->line;
4519                    col = ctxt->input->col;
4520		}
4521                /* something really bad happened in the SAX callback */
4522                if (ctxt->instate != XML_PARSER_CONTENT)
4523                    return;
4524	    }
4525	    ctxt->input->cur = in;
4526	    if (*in == 0xD) {
4527		in++;
4528		if (*in == 0xA) {
4529		    ctxt->input->cur = in;
4530		    in++;
4531		    ctxt->input->line++; ctxt->input->col = 1;
4532		    continue; /* while */
4533		}
4534		in--;
4535	    }
4536	    if (*in == '<') {
4537		return;
4538	    }
4539	    if (*in == '&') {
4540		return;
4541	    }
4542	    SHRINK;
4543	    GROW;
4544            if (ctxt->instate == XML_PARSER_EOF)
4545		return;
4546	    in = ctxt->input->cur;
4547	} while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
4548	nbchar = 0;
4549    }
4550    ctxt->input->line = line;
4551    ctxt->input->col = col;
4552    xmlParseCharDataComplex(ctxt, cdata);
4553}
4554
4555/**
4556 * xmlParseCharDataComplex:
4557 * @ctxt:  an XML parser context
4558 * @cdata:  int indicating whether we are within a CDATA section
4559 *
4560 * parse a CharData section.this is the fallback function
4561 * of xmlParseCharData() when the parsing requires handling
4562 * of non-ASCII characters.
4563 */
4564static void
4565xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
4566    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4567    int nbchar = 0;
4568    int cur, l;
4569    int count = 0;
4570
4571    SHRINK;
4572    GROW;
4573    cur = CUR_CHAR(l);
4574    while ((cur != '<') && /* checked */
4575           (cur != '&') &&
4576	   (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4577	if ((cur == ']') && (NXT(1) == ']') &&
4578	    (NXT(2) == '>')) {
4579	    if (cdata) break;
4580	    else {
4581		xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4582	    }
4583	}
4584	COPY_BUF(l,buf,nbchar,cur);
4585	if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4586	    buf[nbchar] = 0;
4587
4588	    /*
4589	     * OK the segment is to be consumed as chars.
4590	     */
4591	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4592		if (areBlanks(ctxt, buf, nbchar, 0)) {
4593		    if (ctxt->sax->ignorableWhitespace != NULL)
4594			ctxt->sax->ignorableWhitespace(ctxt->userData,
4595			                               buf, nbchar);
4596		} else {
4597		    if (ctxt->sax->characters != NULL)
4598			ctxt->sax->characters(ctxt->userData, buf, nbchar);
4599		    if ((ctxt->sax->characters !=
4600		         ctxt->sax->ignorableWhitespace) &&
4601			(*ctxt->space == -1))
4602			*ctxt->space = -2;
4603		}
4604	    }
4605	    nbchar = 0;
4606            /* something really bad happened in the SAX callback */
4607            if (ctxt->instate != XML_PARSER_CONTENT)
4608                return;
4609	}
4610	count++;
4611	if (count > 50) {
4612	    GROW;
4613	    count = 0;
4614            if (ctxt->instate == XML_PARSER_EOF)
4615		return;
4616	}
4617	NEXTL(l);
4618	cur = CUR_CHAR(l);
4619    }
4620    if (nbchar != 0) {
4621        buf[nbchar] = 0;
4622	/*
4623	 * OK the segment is to be consumed as chars.
4624	 */
4625	if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4626	    if (areBlanks(ctxt, buf, nbchar, 0)) {
4627		if (ctxt->sax->ignorableWhitespace != NULL)
4628		    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4629	    } else {
4630		if (ctxt->sax->characters != NULL)
4631		    ctxt->sax->characters(ctxt->userData, buf, nbchar);
4632		if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4633		    (*ctxt->space == -1))
4634		    *ctxt->space = -2;
4635	    }
4636	}
4637    }
4638    if ((cur != 0) && (!IS_CHAR(cur))) {
4639	/* Generate the error and skip the offending character */
4640        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4641                          "PCDATA invalid Char value %d\n",
4642	                  cur);
4643	NEXTL(l);
4644    }
4645}
4646
4647/**
4648 * xmlParseExternalID:
4649 * @ctxt:  an XML parser context
4650 * @publicID:  a xmlChar** receiving PubidLiteral
4651 * @strict: indicate whether we should restrict parsing to only
4652 *          production [75], see NOTE below
4653 *
4654 * Parse an External ID or a Public ID
4655 *
4656 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4657 *       'PUBLIC' S PubidLiteral S SystemLiteral
4658 *
4659 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4660 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4661 *
4662 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4663 *
4664 * Returns the function returns SystemLiteral and in the second
4665 *                case publicID receives PubidLiteral, is strict is off
4666 *                it is possible to return NULL and have publicID set.
4667 */
4668
4669xmlChar *
4670xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4671    xmlChar *URI = NULL;
4672
4673    SHRINK;
4674
4675    *publicID = NULL;
4676    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4677        SKIP(6);
4678	if (!IS_BLANK_CH(CUR)) {
4679	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4680	                   "Space required after 'SYSTEM'\n");
4681	}
4682        SKIP_BLANKS;
4683	URI = xmlParseSystemLiteral(ctxt);
4684	if (URI == NULL) {
4685	    xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4686        }
4687    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4688        SKIP(6);
4689	if (!IS_BLANK_CH(CUR)) {
4690	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4691		    "Space required after 'PUBLIC'\n");
4692	}
4693        SKIP_BLANKS;
4694	*publicID = xmlParsePubidLiteral(ctxt);
4695	if (*publicID == NULL) {
4696	    xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4697	}
4698	if (strict) {
4699	    /*
4700	     * We don't handle [83] so "S SystemLiteral" is required.
4701	     */
4702	    if (!IS_BLANK_CH(CUR)) {
4703		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4704			"Space required after the Public Identifier\n");
4705	    }
4706	} else {
4707	    /*
4708	     * We handle [83] so we return immediately, if
4709	     * "S SystemLiteral" is not detected. From a purely parsing
4710	     * point of view that's a nice mess.
4711	     */
4712	    const xmlChar *ptr;
4713	    GROW;
4714
4715	    ptr = CUR_PTR;
4716	    if (!IS_BLANK_CH(*ptr)) return(NULL);
4717
4718	    while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
4719	    if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
4720	}
4721        SKIP_BLANKS;
4722	URI = xmlParseSystemLiteral(ctxt);
4723	if (URI == NULL) {
4724	    xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4725        }
4726    }
4727    return(URI);
4728}
4729
4730/**
4731 * xmlParseCommentComplex:
4732 * @ctxt:  an XML parser context
4733 * @buf:  the already parsed part of the buffer
4734 * @len:  number of bytes filles in the buffer
4735 * @size:  allocated size of the buffer
4736 *
4737 * Skip an XML (SGML) comment <!-- .... -->
4738 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4739 *  must not occur within comments. "
4740 * This is the slow routine in case the accelerator for ascii didn't work
4741 *
4742 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4743 */
4744static void
4745xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4746                       size_t len, size_t size) {
4747    int q, ql;
4748    int r, rl;
4749    int cur, l;
4750    size_t count = 0;
4751    int inputid;
4752
4753    inputid = ctxt->input->id;
4754
4755    if (buf == NULL) {
4756        len = 0;
4757	size = XML_PARSER_BUFFER_SIZE;
4758	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4759	if (buf == NULL) {
4760	    xmlErrMemory(ctxt, NULL);
4761	    return;
4762	}
4763    }
4764    GROW;	/* Assure there's enough input data */
4765    q = CUR_CHAR(ql);
4766    if (q == 0)
4767        goto not_terminated;
4768    if (!IS_CHAR(q)) {
4769        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4770                          "xmlParseComment: invalid xmlChar value %d\n",
4771	                  q);
4772	xmlFree (buf);
4773	return;
4774    }
4775    NEXTL(ql);
4776    r = CUR_CHAR(rl);
4777    if (r == 0)
4778        goto not_terminated;
4779    if (!IS_CHAR(r)) {
4780        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4781                          "xmlParseComment: invalid xmlChar value %d\n",
4782	                  q);
4783	xmlFree (buf);
4784	return;
4785    }
4786    NEXTL(rl);
4787    cur = CUR_CHAR(l);
4788    if (cur == 0)
4789        goto not_terminated;
4790    while (IS_CHAR(cur) && /* checked */
4791           ((cur != '>') ||
4792	    (r != '-') || (q != '-'))) {
4793	if ((r == '-') && (q == '-')) {
4794	    xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4795	}
4796        if ((len > XML_MAX_TEXT_LENGTH) &&
4797            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4798            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4799                         "Comment too big found", NULL);
4800            xmlFree (buf);
4801            return;
4802        }
4803	if (len + 5 >= size) {
4804	    xmlChar *new_buf;
4805            size_t new_size;
4806
4807	    new_size = size * 2;
4808	    new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4809	    if (new_buf == NULL) {
4810		xmlFree (buf);
4811		xmlErrMemory(ctxt, NULL);
4812		return;
4813	    }
4814	    buf = new_buf;
4815            size = new_size;
4816	}
4817	COPY_BUF(ql,buf,len,q);
4818	q = r;
4819	ql = rl;
4820	r = cur;
4821	rl = l;
4822
4823	count++;
4824	if (count > 50) {
4825	    GROW;
4826	    count = 0;
4827            if (ctxt->instate == XML_PARSER_EOF) {
4828		xmlFree(buf);
4829		return;
4830            }
4831	}
4832	NEXTL(l);
4833	cur = CUR_CHAR(l);
4834	if (cur == 0) {
4835	    SHRINK;
4836	    GROW;
4837	    cur = CUR_CHAR(l);
4838	}
4839    }
4840    buf[len] = 0;
4841    if (cur == 0) {
4842	xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4843	                     "Comment not terminated \n<!--%.50s\n", buf);
4844    } else if (!IS_CHAR(cur)) {
4845        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4846                          "xmlParseComment: invalid xmlChar value %d\n",
4847	                  cur);
4848    } else {
4849	if (inputid != ctxt->input->id) {
4850	    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4851		"Comment doesn't start and stop in the same entity\n");
4852	}
4853        NEXT;
4854	if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4855	    (!ctxt->disableSAX))
4856	    ctxt->sax->comment(ctxt->userData, buf);
4857    }
4858    xmlFree(buf);
4859    return;
4860not_terminated:
4861    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4862			 "Comment not terminated\n", NULL);
4863    xmlFree(buf);
4864    return;
4865}
4866
4867/**
4868 * xmlParseComment:
4869 * @ctxt:  an XML parser context
4870 *
4871 * Skip an XML (SGML) comment <!-- .... -->
4872 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4873 *  must not occur within comments. "
4874 *
4875 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4876 */
4877void
4878xmlParseComment(xmlParserCtxtPtr ctxt) {
4879    xmlChar *buf = NULL;
4880    size_t size = XML_PARSER_BUFFER_SIZE;
4881    size_t len = 0;
4882    xmlParserInputState state;
4883    const xmlChar *in;
4884    size_t nbchar = 0;
4885    int ccol;
4886    int inputid;
4887
4888    /*
4889     * Check that there is a comment right here.
4890     */
4891    if ((RAW != '<') || (NXT(1) != '!') ||
4892        (NXT(2) != '-') || (NXT(3) != '-')) return;
4893    state = ctxt->instate;
4894    ctxt->instate = XML_PARSER_COMMENT;
4895    inputid = ctxt->input->id;
4896    SKIP(4);
4897    SHRINK;
4898    GROW;
4899
4900    /*
4901     * Accelerated common case where input don't need to be
4902     * modified before passing it to the handler.
4903     */
4904    in = ctxt->input->cur;
4905    do {
4906	if (*in == 0xA) {
4907	    do {
4908		ctxt->input->line++; ctxt->input->col = 1;
4909		in++;
4910	    } while (*in == 0xA);
4911	}
4912get_more:
4913        ccol = ctxt->input->col;
4914	while (((*in > '-') && (*in <= 0x7F)) ||
4915	       ((*in >= 0x20) && (*in < '-')) ||
4916	       (*in == 0x09)) {
4917		    in++;
4918		    ccol++;
4919	}
4920	ctxt->input->col = ccol;
4921	if (*in == 0xA) {
4922	    do {
4923		ctxt->input->line++; ctxt->input->col = 1;
4924		in++;
4925	    } while (*in == 0xA);
4926	    goto get_more;
4927	}
4928	nbchar = in - ctxt->input->cur;
4929	/*
4930	 * save current set of data
4931	 */
4932	if (nbchar > 0) {
4933	    if ((ctxt->sax != NULL) &&
4934		(ctxt->sax->comment != NULL)) {
4935		if (buf == NULL) {
4936		    if ((*in == '-') && (in[1] == '-'))
4937		        size = nbchar + 1;
4938		    else
4939		        size = XML_PARSER_BUFFER_SIZE + nbchar;
4940		    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4941		    if (buf == NULL) {
4942		        xmlErrMemory(ctxt, NULL);
4943			ctxt->instate = state;
4944			return;
4945		    }
4946		    len = 0;
4947		} else if (len + nbchar + 1 >= size) {
4948		    xmlChar *new_buf;
4949		    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
4950		    new_buf = (xmlChar *) xmlRealloc(buf,
4951		                                     size * sizeof(xmlChar));
4952		    if (new_buf == NULL) {
4953		        xmlFree (buf);
4954			xmlErrMemory(ctxt, NULL);
4955			ctxt->instate = state;
4956			return;
4957		    }
4958		    buf = new_buf;
4959		}
4960		memcpy(&buf[len], ctxt->input->cur, nbchar);
4961		len += nbchar;
4962		buf[len] = 0;
4963	    }
4964	}
4965        if ((len > XML_MAX_TEXT_LENGTH) &&
4966            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4967            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4968                         "Comment too big found", NULL);
4969            xmlFree (buf);
4970            return;
4971        }
4972	ctxt->input->cur = in;
4973	if (*in == 0xA) {
4974	    in++;
4975	    ctxt->input->line++; ctxt->input->col = 1;
4976	}
4977	if (*in == 0xD) {
4978	    in++;
4979	    if (*in == 0xA) {
4980		ctxt->input->cur = in;
4981		in++;
4982		ctxt->input->line++; ctxt->input->col = 1;
4983		continue; /* while */
4984	    }
4985	    in--;
4986	}
4987	SHRINK;
4988	GROW;
4989        if (ctxt->instate == XML_PARSER_EOF) {
4990            xmlFree(buf);
4991            return;
4992        }
4993	in = ctxt->input->cur;
4994	if (*in == '-') {
4995	    if (in[1] == '-') {
4996	        if (in[2] == '>') {
4997		    if (ctxt->input->id != inputid) {
4998			xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4999			"comment doesn't start and stop in the same entity\n");
5000		    }
5001		    SKIP(3);
5002		    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5003		        (!ctxt->disableSAX)) {
5004			if (buf != NULL)
5005			    ctxt->sax->comment(ctxt->userData, buf);
5006			else
5007			    ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5008		    }
5009		    if (buf != NULL)
5010		        xmlFree(buf);
5011		    if (ctxt->instate != XML_PARSER_EOF)
5012			ctxt->instate = state;
5013		    return;
5014		}
5015		if (buf != NULL) {
5016		    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5017		                      "Double hyphen within comment: "
5018                                      "<!--%.50s\n",
5019				      buf);
5020		} else
5021		    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5022		                      "Double hyphen within comment\n", NULL);
5023		in++;
5024		ctxt->input->col++;
5025	    }
5026	    in++;
5027	    ctxt->input->col++;
5028	    goto get_more;
5029	}
5030    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
5031    xmlParseCommentComplex(ctxt, buf, len, size);
5032    ctxt->instate = state;
5033    return;
5034}
5035
5036
5037/**
5038 * xmlParsePITarget:
5039 * @ctxt:  an XML parser context
5040 *
5041 * parse the name of a PI
5042 *
5043 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5044 *
5045 * Returns the PITarget name or NULL
5046 */
5047
5048const xmlChar *
5049xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5050    const xmlChar *name;
5051
5052    name = xmlParseName(ctxt);
5053    if ((name != NULL) &&
5054        ((name[0] == 'x') || (name[0] == 'X')) &&
5055        ((name[1] == 'm') || (name[1] == 'M')) &&
5056        ((name[2] == 'l') || (name[2] == 'L'))) {
5057	int i;
5058	if ((name[0] == 'x') && (name[1] == 'm') &&
5059	    (name[2] == 'l') && (name[3] == 0)) {
5060	    xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5061		 "XML declaration allowed only at the start of the document\n");
5062	    return(name);
5063	} else if (name[3] == 0) {
5064	    xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5065	    return(name);
5066	}
5067	for (i = 0;;i++) {
5068	    if (xmlW3CPIs[i] == NULL) break;
5069	    if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5070	        return(name);
5071	}
5072	xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5073		      "xmlParsePITarget: invalid name prefix 'xml'\n",
5074		      NULL, NULL);
5075    }
5076    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5077	xmlNsErr(ctxt, XML_NS_ERR_COLON,
5078		 "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
5079    }
5080    return(name);
5081}
5082
5083#ifdef LIBXML_CATALOG_ENABLED
5084/**
5085 * xmlParseCatalogPI:
5086 * @ctxt:  an XML parser context
5087 * @catalog:  the PI value string
5088 *
5089 * parse an XML Catalog Processing Instruction.
5090 *
5091 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5092 *
5093 * Occurs only if allowed by the user and if happening in the Misc
5094 * part of the document before any doctype informations
5095 * This will add the given catalog to the parsing context in order
5096 * to be used if there is a resolution need further down in the document
5097 */
5098
5099static void
5100xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5101    xmlChar *URL = NULL;
5102    const xmlChar *tmp, *base;
5103    xmlChar marker;
5104
5105    tmp = catalog;
5106    while (IS_BLANK_CH(*tmp)) tmp++;
5107    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5108	goto error;
5109    tmp += 7;
5110    while (IS_BLANK_CH(*tmp)) tmp++;
5111    if (*tmp != '=') {
5112	return;
5113    }
5114    tmp++;
5115    while (IS_BLANK_CH(*tmp)) tmp++;
5116    marker = *tmp;
5117    if ((marker != '\'') && (marker != '"'))
5118	goto error;
5119    tmp++;
5120    base = tmp;
5121    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5122    if (*tmp == 0)
5123	goto error;
5124    URL = xmlStrndup(base, tmp - base);
5125    tmp++;
5126    while (IS_BLANK_CH(*tmp)) tmp++;
5127    if (*tmp != 0)
5128	goto error;
5129
5130    if (URL != NULL) {
5131	ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5132	xmlFree(URL);
5133    }
5134    return;
5135
5136error:
5137    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5138	          "Catalog PI syntax error: %s\n",
5139		  catalog, NULL);
5140    if (URL != NULL)
5141	xmlFree(URL);
5142}
5143#endif
5144
5145/**
5146 * xmlParsePI:
5147 * @ctxt:  an XML parser context
5148 *
5149 * parse an XML Processing Instruction.
5150 *
5151 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5152 *
5153 * The processing is transfered to SAX once parsed.
5154 */
5155
5156void
5157xmlParsePI(xmlParserCtxtPtr ctxt) {
5158    xmlChar *buf = NULL;
5159    size_t len = 0;
5160    size_t size = XML_PARSER_BUFFER_SIZE;
5161    int cur, l;
5162    const xmlChar *target;
5163    xmlParserInputState state;
5164    int count = 0;
5165
5166    if ((RAW == '<') && (NXT(1) == '?')) {
5167	xmlParserInputPtr input = ctxt->input;
5168	state = ctxt->instate;
5169        ctxt->instate = XML_PARSER_PI;
5170	/*
5171	 * this is a Processing Instruction.
5172	 */
5173	SKIP(2);
5174	SHRINK;
5175
5176	/*
5177	 * Parse the target name and check for special support like
5178	 * namespace.
5179	 */
5180        target = xmlParsePITarget(ctxt);
5181	if (target != NULL) {
5182	    if ((RAW == '?') && (NXT(1) == '>')) {
5183		if (input != ctxt->input) {
5184		    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5185	    "PI declaration doesn't start and stop in the same entity\n");
5186		}
5187		SKIP(2);
5188
5189		/*
5190		 * SAX: PI detected.
5191		 */
5192		if ((ctxt->sax) && (!ctxt->disableSAX) &&
5193		    (ctxt->sax->processingInstruction != NULL))
5194		    ctxt->sax->processingInstruction(ctxt->userData,
5195		                                     target, NULL);
5196		if (ctxt->instate != XML_PARSER_EOF)
5197		    ctxt->instate = state;
5198		return;
5199	    }
5200	    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
5201	    if (buf == NULL) {
5202		xmlErrMemory(ctxt, NULL);
5203		ctxt->instate = state;
5204		return;
5205	    }
5206	    cur = CUR;
5207	    if (!IS_BLANK(cur)) {
5208		xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5209			  "ParsePI: PI %s space expected\n", target);
5210	    }
5211            SKIP_BLANKS;
5212	    cur = CUR_CHAR(l);
5213	    while (IS_CHAR(cur) && /* checked */
5214		   ((cur != '?') || (NXT(1) != '>'))) {
5215		if (len + 5 >= size) {
5216		    xmlChar *tmp;
5217                    size_t new_size = size * 2;
5218		    tmp = (xmlChar *) xmlRealloc(buf, new_size);
5219		    if (tmp == NULL) {
5220			xmlErrMemory(ctxt, NULL);
5221			xmlFree(buf);
5222			ctxt->instate = state;
5223			return;
5224		    }
5225		    buf = tmp;
5226                    size = new_size;
5227		}
5228		count++;
5229		if (count > 50) {
5230		    GROW;
5231                    if (ctxt->instate == XML_PARSER_EOF) {
5232                        xmlFree(buf);
5233                        return;
5234                    }
5235		    count = 0;
5236                    if ((len > XML_MAX_TEXT_LENGTH) &&
5237                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
5238                        xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5239                                          "PI %s too big found", target);
5240                        xmlFree(buf);
5241                        ctxt->instate = state;
5242                        return;
5243                    }
5244		}
5245		COPY_BUF(l,buf,len,cur);
5246		NEXTL(l);
5247		cur = CUR_CHAR(l);
5248		if (cur == 0) {
5249		    SHRINK;
5250		    GROW;
5251		    cur = CUR_CHAR(l);
5252		}
5253	    }
5254            if ((len > XML_MAX_TEXT_LENGTH) &&
5255                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
5256                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5257                                  "PI %s too big found", target);
5258                xmlFree(buf);
5259                ctxt->instate = state;
5260                return;
5261            }
5262	    buf[len] = 0;
5263	    if (cur != '?') {
5264		xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5265		      "ParsePI: PI %s never end ...\n", target);
5266	    } else {
5267		if (input != ctxt->input) {
5268		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5269	    "PI declaration doesn't start and stop in the same entity\n");
5270		}
5271		SKIP(2);
5272
5273#ifdef LIBXML_CATALOG_ENABLED
5274		if (((state == XML_PARSER_MISC) ||
5275	             (state == XML_PARSER_START)) &&
5276		    (xmlStrEqual(target, XML_CATALOG_PI))) {
5277		    xmlCatalogAllow allow = xmlCatalogGetDefaults();
5278		    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5279			(allow == XML_CATA_ALLOW_ALL))
5280			xmlParseCatalogPI(ctxt, buf);
5281		}
5282#endif
5283
5284
5285		/*
5286		 * SAX: PI detected.
5287		 */
5288		if ((ctxt->sax) && (!ctxt->disableSAX) &&
5289		    (ctxt->sax->processingInstruction != NULL))
5290		    ctxt->sax->processingInstruction(ctxt->userData,
5291		                                     target, buf);
5292	    }
5293	    xmlFree(buf);
5294	} else {
5295	    xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5296	}
5297	if (ctxt->instate != XML_PARSER_EOF)
5298	    ctxt->instate = state;
5299    }
5300}
5301
5302/**
5303 * xmlParseNotationDecl:
5304 * @ctxt:  an XML parser context
5305 *
5306 * parse a notation declaration
5307 *
5308 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5309 *
5310 * Hence there is actually 3 choices:
5311 *     'PUBLIC' S PubidLiteral
5312 *     'PUBLIC' S PubidLiteral S SystemLiteral
5313 * and 'SYSTEM' S SystemLiteral
5314 *
5315 * See the NOTE on xmlParseExternalID().
5316 */
5317
5318void
5319xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5320    const xmlChar *name;
5321    xmlChar *Pubid;
5322    xmlChar *Systemid;
5323
5324    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5325	xmlParserInputPtr input = ctxt->input;
5326	SHRINK;
5327	SKIP(10);
5328	if (!IS_BLANK_CH(CUR)) {
5329	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5330			   "Space required after '<!NOTATION'\n");
5331	    return;
5332	}
5333	SKIP_BLANKS;
5334
5335        name = xmlParseName(ctxt);
5336	if (name == NULL) {
5337	    xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5338	    return;
5339	}
5340	if (!IS_BLANK_CH(CUR)) {
5341	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5342		     "Space required after the NOTATION name'\n");
5343	    return;
5344	}
5345	if (xmlStrchr(name, ':') != NULL) {
5346	    xmlNsErr(ctxt, XML_NS_ERR_COLON,
5347		     "colon are forbidden from notation names '%s'\n",
5348		     name, NULL, NULL);
5349	}
5350	SKIP_BLANKS;
5351
5352	/*
5353	 * Parse the IDs.
5354	 */
5355	Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5356	SKIP_BLANKS;
5357
5358	if (RAW == '>') {
5359	    if (input != ctxt->input) {
5360		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5361	"Notation declaration doesn't start and stop in the same entity\n");
5362	    }
5363	    NEXT;
5364	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5365		(ctxt->sax->notationDecl != NULL))
5366		ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5367	} else {
5368	    xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5369	}
5370	if (Systemid != NULL) xmlFree(Systemid);
5371	if (Pubid != NULL) xmlFree(Pubid);
5372    }
5373}
5374
5375/**
5376 * xmlParseEntityDecl:
5377 * @ctxt:  an XML parser context
5378 *
5379 * parse <!ENTITY declarations
5380 *
5381 * [70] EntityDecl ::= GEDecl | PEDecl
5382 *
5383 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5384 *
5385 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5386 *
5387 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5388 *
5389 * [74] PEDef ::= EntityValue | ExternalID
5390 *
5391 * [76] NDataDecl ::= S 'NDATA' S Name
5392 *
5393 * [ VC: Notation Declared ]
5394 * The Name must match the declared name of a notation.
5395 */
5396
5397void
5398xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5399    const xmlChar *name = NULL;
5400    xmlChar *value = NULL;
5401    xmlChar *URI = NULL, *literal = NULL;
5402    const xmlChar *ndata = NULL;
5403    int isParameter = 0;
5404    xmlChar *orig = NULL;
5405    int skipped;
5406
5407    /* GROW; done in the caller */
5408    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
5409	xmlParserInputPtr input = ctxt->input;
5410	SHRINK;
5411	SKIP(8);
5412	skipped = SKIP_BLANKS;
5413	if (skipped == 0) {
5414	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5415			   "Space required after '<!ENTITY'\n");
5416	}
5417
5418	if (RAW == '%') {
5419	    NEXT;
5420	    skipped = SKIP_BLANKS;
5421	    if (skipped == 0) {
5422		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5423			       "Space required after '%'\n");
5424	    }
5425	    isParameter = 1;
5426	}
5427
5428        name = xmlParseName(ctxt);
5429	if (name == NULL) {
5430	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5431	                   "xmlParseEntityDecl: no name\n");
5432            return;
5433	}
5434	if (xmlStrchr(name, ':') != NULL) {
5435	    xmlNsErr(ctxt, XML_NS_ERR_COLON,
5436		     "colon are forbidden from entities names '%s'\n",
5437		     name, NULL, NULL);
5438	}
5439        skipped = SKIP_BLANKS;
5440	if (skipped == 0) {
5441	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5442			   "Space required after the entity name\n");
5443	}
5444
5445	ctxt->instate = XML_PARSER_ENTITY_DECL;
5446	/*
5447	 * handle the various case of definitions...
5448	 */
5449	if (isParameter) {
5450	    if ((RAW == '"') || (RAW == '\'')) {
5451	        value = xmlParseEntityValue(ctxt, &orig);
5452		if (value) {
5453		    if ((ctxt->sax != NULL) &&
5454			(!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5455			ctxt->sax->entityDecl(ctxt->userData, name,
5456		                    XML_INTERNAL_PARAMETER_ENTITY,
5457				    NULL, NULL, value);
5458		}
5459	    } else {
5460	        URI = xmlParseExternalID(ctxt, &literal, 1);
5461		if ((URI == NULL) && (literal == NULL)) {
5462		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5463		}
5464		if (URI) {
5465		    xmlURIPtr uri;
5466
5467		    uri = xmlParseURI((const char *) URI);
5468		    if (uri == NULL) {
5469		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5470				     "Invalid URI: %s\n", URI);
5471			/*
5472			 * This really ought to be a well formedness error
5473			 * but the XML Core WG decided otherwise c.f. issue
5474			 * E26 of the XML erratas.
5475			 */
5476		    } else {
5477			if (uri->fragment != NULL) {
5478			    /*
5479			     * Okay this is foolish to block those but not
5480			     * invalid URIs.
5481			     */
5482			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5483			} else {
5484			    if ((ctxt->sax != NULL) &&
5485				(!ctxt->disableSAX) &&
5486				(ctxt->sax->entityDecl != NULL))
5487				ctxt->sax->entityDecl(ctxt->userData, name,
5488					    XML_EXTERNAL_PARAMETER_ENTITY,
5489					    literal, URI, NULL);
5490			}
5491			xmlFreeURI(uri);
5492		    }
5493		}
5494	    }
5495	} else {
5496	    if ((RAW == '"') || (RAW == '\'')) {
5497	        value = xmlParseEntityValue(ctxt, &orig);
5498		if ((ctxt->sax != NULL) &&
5499		    (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5500		    ctxt->sax->entityDecl(ctxt->userData, name,
5501				XML_INTERNAL_GENERAL_ENTITY,
5502				NULL, NULL, value);
5503		/*
5504		 * For expat compatibility in SAX mode.
5505		 */
5506		if ((ctxt->myDoc == NULL) ||
5507		    (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5508		    if (ctxt->myDoc == NULL) {
5509			ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5510			if (ctxt->myDoc == NULL) {
5511			    xmlErrMemory(ctxt, "New Doc failed");
5512			    return;
5513			}
5514			ctxt->myDoc->properties = XML_DOC_INTERNAL;
5515		    }
5516		    if (ctxt->myDoc->intSubset == NULL)
5517			ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5518					    BAD_CAST "fake", NULL, NULL);
5519
5520		    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5521			              NULL, NULL, value);
5522		}
5523	    } else {
5524	        URI = xmlParseExternalID(ctxt, &literal, 1);
5525		if ((URI == NULL) && (literal == NULL)) {
5526		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5527		}
5528		if (URI) {
5529		    xmlURIPtr uri;
5530
5531		    uri = xmlParseURI((const char *)URI);
5532		    if (uri == NULL) {
5533		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5534				     "Invalid URI: %s\n", URI);
5535			/*
5536			 * This really ought to be a well formedness error
5537			 * but the XML Core WG decided otherwise c.f. issue
5538			 * E26 of the XML erratas.
5539			 */
5540		    } else {
5541			if (uri->fragment != NULL) {
5542			    /*
5543			     * Okay this is foolish to block those but not
5544			     * invalid URIs.
5545			     */
5546			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5547			}
5548			xmlFreeURI(uri);
5549		    }
5550		}
5551		if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
5552		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5553				   "Space required before 'NDATA'\n");
5554		}
5555		SKIP_BLANKS;
5556		if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5557		    SKIP(5);
5558		    if (!IS_BLANK_CH(CUR)) {
5559			xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5560				       "Space required after 'NDATA'\n");
5561		    }
5562		    SKIP_BLANKS;
5563		    ndata = xmlParseName(ctxt);
5564		    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5565		        (ctxt->sax->unparsedEntityDecl != NULL))
5566			ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5567				    literal, URI, ndata);
5568		} else {
5569		    if ((ctxt->sax != NULL) &&
5570		        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5571			ctxt->sax->entityDecl(ctxt->userData, name,
5572				    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5573				    literal, URI, NULL);
5574		    /*
5575		     * For expat compatibility in SAX mode.
5576		     * assuming the entity repalcement was asked for
5577		     */
5578		    if ((ctxt->replaceEntities != 0) &&
5579			((ctxt->myDoc == NULL) ||
5580			(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5581			if (ctxt->myDoc == NULL) {
5582			    ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5583			    if (ctxt->myDoc == NULL) {
5584			        xmlErrMemory(ctxt, "New Doc failed");
5585				return;
5586			    }
5587			    ctxt->myDoc->properties = XML_DOC_INTERNAL;
5588			}
5589
5590			if (ctxt->myDoc->intSubset == NULL)
5591			    ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5592						BAD_CAST "fake", NULL, NULL);
5593			xmlSAX2EntityDecl(ctxt, name,
5594				          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5595				          literal, URI, NULL);
5596		    }
5597		}
5598	    }
5599	}
5600	if (ctxt->instate == XML_PARSER_EOF)
5601	    return;
5602	SKIP_BLANKS;
5603	if (RAW != '>') {
5604	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5605	            "xmlParseEntityDecl: entity %s not terminated\n", name);
5606	} else {
5607	    if (input != ctxt->input) {
5608		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5609	"Entity declaration doesn't start and stop in the same entity\n");
5610	    }
5611	    NEXT;
5612	}
5613	if (orig != NULL) {
5614	    /*
5615	     * Ugly mechanism to save the raw entity value.
5616	     */
5617	    xmlEntityPtr cur = NULL;
5618
5619	    if (isParameter) {
5620	        if ((ctxt->sax != NULL) &&
5621		    (ctxt->sax->getParameterEntity != NULL))
5622		    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5623	    } else {
5624	        if ((ctxt->sax != NULL) &&
5625		    (ctxt->sax->getEntity != NULL))
5626		    cur = ctxt->sax->getEntity(ctxt->userData, name);
5627		if ((cur == NULL) && (ctxt->userData==ctxt)) {
5628		    cur = xmlSAX2GetEntity(ctxt, name);
5629		}
5630	    }
5631            if (cur != NULL) {
5632	        if (cur->orig != NULL)
5633		    xmlFree(orig);
5634		else
5635		    cur->orig = orig;
5636	    } else
5637		xmlFree(orig);
5638	}
5639	if (value != NULL) xmlFree(value);
5640	if (URI != NULL) xmlFree(URI);
5641	if (literal != NULL) xmlFree(literal);
5642    }
5643}
5644
5645/**
5646 * xmlParseDefaultDecl:
5647 * @ctxt:  an XML parser context
5648 * @value:  Receive a possible fixed default value for the attribute
5649 *
5650 * Parse an attribute default declaration
5651 *
5652 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5653 *
5654 * [ VC: Required Attribute ]
5655 * if the default declaration is the keyword #REQUIRED, then the
5656 * attribute must be specified for all elements of the type in the
5657 * attribute-list declaration.
5658 *
5659 * [ VC: Attribute Default Legal ]
5660 * The declared default value must meet the lexical constraints of
5661 * the declared attribute type c.f. xmlValidateAttributeDecl()
5662 *
5663 * [ VC: Fixed Attribute Default ]
5664 * if an attribute has a default value declared with the #FIXED
5665 * keyword, instances of that attribute must match the default value.
5666 *
5667 * [ WFC: No < in Attribute Values ]
5668 * handled in xmlParseAttValue()
5669 *
5670 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5671 *          or XML_ATTRIBUTE_FIXED.
5672 */
5673
5674int
5675xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5676    int val;
5677    xmlChar *ret;
5678
5679    *value = NULL;
5680    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5681	SKIP(9);
5682	return(XML_ATTRIBUTE_REQUIRED);
5683    }
5684    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5685	SKIP(8);
5686	return(XML_ATTRIBUTE_IMPLIED);
5687    }
5688    val = XML_ATTRIBUTE_NONE;
5689    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5690	SKIP(6);
5691	val = XML_ATTRIBUTE_FIXED;
5692	if (!IS_BLANK_CH(CUR)) {
5693	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5694			   "Space required after '#FIXED'\n");
5695	}
5696	SKIP_BLANKS;
5697    }
5698    ret = xmlParseAttValue(ctxt);
5699    ctxt->instate = XML_PARSER_DTD;
5700    if (ret == NULL) {
5701	xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5702		       "Attribute default value declaration error\n");
5703    } else
5704        *value = ret;
5705    return(val);
5706}
5707
5708/**
5709 * xmlParseNotationType:
5710 * @ctxt:  an XML parser context
5711 *
5712 * parse an Notation attribute type.
5713 *
5714 * Note: the leading 'NOTATION' S part has already being parsed...
5715 *
5716 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5717 *
5718 * [ VC: Notation Attributes ]
5719 * Values of this type must match one of the notation names included
5720 * in the declaration; all notation names in the declaration must be declared.
5721 *
5722 * Returns: the notation attribute tree built while parsing
5723 */
5724
5725xmlEnumerationPtr
5726xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5727    const xmlChar *name;
5728    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5729
5730    if (RAW != '(') {
5731	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5732	return(NULL);
5733    }
5734    SHRINK;
5735    do {
5736        NEXT;
5737	SKIP_BLANKS;
5738        name = xmlParseName(ctxt);
5739	if (name == NULL) {
5740	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5741			   "Name expected in NOTATION declaration\n");
5742            xmlFreeEnumeration(ret);
5743	    return(NULL);
5744	}
5745	tmp = ret;
5746	while (tmp != NULL) {
5747	    if (xmlStrEqual(name, tmp->name)) {
5748		xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5749	  "standalone: attribute notation value token %s duplicated\n",
5750				 name, NULL);
5751		if (!xmlDictOwns(ctxt->dict, name))
5752		    xmlFree((xmlChar *) name);
5753		break;
5754	    }
5755	    tmp = tmp->next;
5756	}
5757	if (tmp == NULL) {
5758	    cur = xmlCreateEnumeration(name);
5759	    if (cur == NULL) {
5760                xmlFreeEnumeration(ret);
5761                return(NULL);
5762            }
5763	    if (last == NULL) ret = last = cur;
5764	    else {
5765		last->next = cur;
5766		last = cur;
5767	    }
5768	}
5769	SKIP_BLANKS;
5770    } while (RAW == '|');
5771    if (RAW != ')') {
5772	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5773        xmlFreeEnumeration(ret);
5774	return(NULL);
5775    }
5776    NEXT;
5777    return(ret);
5778}
5779
5780/**
5781 * xmlParseEnumerationType:
5782 * @ctxt:  an XML parser context
5783 *
5784 * parse an Enumeration attribute type.
5785 *
5786 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5787 *
5788 * [ VC: Enumeration ]
5789 * Values of this type must match one of the Nmtoken tokens in
5790 * the declaration
5791 *
5792 * Returns: the enumeration attribute tree built while parsing
5793 */
5794
5795xmlEnumerationPtr
5796xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5797    xmlChar *name;
5798    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5799
5800    if (RAW != '(') {
5801	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5802	return(NULL);
5803    }
5804    SHRINK;
5805    do {
5806        NEXT;
5807	SKIP_BLANKS;
5808        name = xmlParseNmtoken(ctxt);
5809	if (name == NULL) {
5810	    xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5811	    return(ret);
5812	}
5813	tmp = ret;
5814	while (tmp != NULL) {
5815	    if (xmlStrEqual(name, tmp->name)) {
5816		xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5817	  "standalone: attribute enumeration value token %s duplicated\n",
5818				 name, NULL);
5819		if (!xmlDictOwns(ctxt->dict, name))
5820		    xmlFree(name);
5821		break;
5822	    }
5823	    tmp = tmp->next;
5824	}
5825	if (tmp == NULL) {
5826	    cur = xmlCreateEnumeration(name);
5827	    if (!xmlDictOwns(ctxt->dict, name))
5828		xmlFree(name);
5829	    if (cur == NULL) {
5830                xmlFreeEnumeration(ret);
5831                return(NULL);
5832            }
5833	    if (last == NULL) ret = last = cur;
5834	    else {
5835		last->next = cur;
5836		last = cur;
5837	    }
5838	}
5839	SKIP_BLANKS;
5840    } while (RAW == '|');
5841    if (RAW != ')') {
5842	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5843	return(ret);
5844    }
5845    NEXT;
5846    return(ret);
5847}
5848
5849/**
5850 * xmlParseEnumeratedType:
5851 * @ctxt:  an XML parser context
5852 * @tree:  the enumeration tree built while parsing
5853 *
5854 * parse an Enumerated attribute type.
5855 *
5856 * [57] EnumeratedType ::= NotationType | Enumeration
5857 *
5858 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5859 *
5860 *
5861 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5862 */
5863
5864int
5865xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5866    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5867	SKIP(8);
5868	if (!IS_BLANK_CH(CUR)) {
5869	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5870			   "Space required after 'NOTATION'\n");
5871	    return(0);
5872	}
5873        SKIP_BLANKS;
5874	*tree = xmlParseNotationType(ctxt);
5875	if (*tree == NULL) return(0);
5876	return(XML_ATTRIBUTE_NOTATION);
5877    }
5878    *tree = xmlParseEnumerationType(ctxt);
5879    if (*tree == NULL) return(0);
5880    return(XML_ATTRIBUTE_ENUMERATION);
5881}
5882
5883/**
5884 * xmlParseAttributeType:
5885 * @ctxt:  an XML parser context
5886 * @tree:  the enumeration tree built while parsing
5887 *
5888 * parse the Attribute list def for an element
5889 *
5890 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5891 *
5892 * [55] StringType ::= 'CDATA'
5893 *
5894 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5895 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5896 *
5897 * Validity constraints for attribute values syntax are checked in
5898 * xmlValidateAttributeValue()
5899 *
5900 * [ VC: ID ]
5901 * Values of type ID must match the Name production. A name must not
5902 * appear more than once in an XML document as a value of this type;
5903 * i.e., ID values must uniquely identify the elements which bear them.
5904 *
5905 * [ VC: One ID per Element Type ]
5906 * No element type may have more than one ID attribute specified.
5907 *
5908 * [ VC: ID Attribute Default ]
5909 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5910 *
5911 * [ VC: IDREF ]
5912 * Values of type IDREF must match the Name production, and values
5913 * of type IDREFS must match Names; each IDREF Name must match the value
5914 * of an ID attribute on some element in the XML document; i.e. IDREF
5915 * values must match the value of some ID attribute.
5916 *
5917 * [ VC: Entity Name ]
5918 * Values of type ENTITY must match the Name production, values
5919 * of type ENTITIES must match Names; each Entity Name must match the
5920 * name of an unparsed entity declared in the DTD.
5921 *
5922 * [ VC: Name Token ]
5923 * Values of type NMTOKEN must match the Nmtoken production; values
5924 * of type NMTOKENS must match Nmtokens.
5925 *
5926 * Returns the attribute type
5927 */
5928int
5929xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5930    SHRINK;
5931    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
5932	SKIP(5);
5933	return(XML_ATTRIBUTE_CDATA);
5934     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
5935	SKIP(6);
5936	return(XML_ATTRIBUTE_IDREFS);
5937     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
5938	SKIP(5);
5939	return(XML_ATTRIBUTE_IDREF);
5940     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
5941        SKIP(2);
5942	return(XML_ATTRIBUTE_ID);
5943     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5944	SKIP(6);
5945	return(XML_ATTRIBUTE_ENTITY);
5946     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
5947	SKIP(8);
5948	return(XML_ATTRIBUTE_ENTITIES);
5949     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
5950	SKIP(8);
5951	return(XML_ATTRIBUTE_NMTOKENS);
5952     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
5953	SKIP(7);
5954	return(XML_ATTRIBUTE_NMTOKEN);
5955     }
5956     return(xmlParseEnumeratedType(ctxt, tree));
5957}
5958
5959/**
5960 * xmlParseAttributeListDecl:
5961 * @ctxt:  an XML parser context
5962 *
5963 * : parse the Attribute list def for an element
5964 *
5965 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
5966 *
5967 * [53] AttDef ::= S Name S AttType S DefaultDecl
5968 *
5969 */
5970void
5971xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
5972    const xmlChar *elemName;
5973    const xmlChar *attrName;
5974    xmlEnumerationPtr tree;
5975
5976    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
5977	xmlParserInputPtr input = ctxt->input;
5978
5979	SKIP(9);
5980	if (!IS_BLANK_CH(CUR)) {
5981	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5982		                 "Space required after '<!ATTLIST'\n");
5983	}
5984        SKIP_BLANKS;
5985        elemName = xmlParseName(ctxt);
5986	if (elemName == NULL) {
5987	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5988			   "ATTLIST: no name for Element\n");
5989	    return;
5990	}
5991	SKIP_BLANKS;
5992	GROW;
5993	while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
5994	    const xmlChar *check = CUR_PTR;
5995	    int type;
5996	    int def;
5997	    xmlChar *defaultValue = NULL;
5998
5999	    GROW;
6000            tree = NULL;
6001	    attrName = xmlParseName(ctxt);
6002	    if (attrName == NULL) {
6003		xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6004			       "ATTLIST: no name for Attribute\n");
6005		break;
6006	    }
6007	    GROW;
6008	    if (!IS_BLANK_CH(CUR)) {
6009		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6010		        "Space required after the attribute name\n");
6011		break;
6012	    }
6013	    SKIP_BLANKS;
6014
6015	    type = xmlParseAttributeType(ctxt, &tree);
6016	    if (type <= 0) {
6017	        break;
6018	    }
6019
6020	    GROW;
6021	    if (!IS_BLANK_CH(CUR)) {
6022		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6023			       "Space required after the attribute type\n");
6024	        if (tree != NULL)
6025		    xmlFreeEnumeration(tree);
6026		break;
6027	    }
6028	    SKIP_BLANKS;
6029
6030	    def = xmlParseDefaultDecl(ctxt, &defaultValue);
6031	    if (def <= 0) {
6032                if (defaultValue != NULL)
6033		    xmlFree(defaultValue);
6034	        if (tree != NULL)
6035		    xmlFreeEnumeration(tree);
6036	        break;
6037	    }
6038	    if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6039	        xmlAttrNormalizeSpace(defaultValue, defaultValue);
6040
6041	    GROW;
6042            if (RAW != '>') {
6043		if (!IS_BLANK_CH(CUR)) {
6044		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6045			"Space required after the attribute default value\n");
6046		    if (defaultValue != NULL)
6047			xmlFree(defaultValue);
6048		    if (tree != NULL)
6049			xmlFreeEnumeration(tree);
6050		    break;
6051		}
6052		SKIP_BLANKS;
6053	    }
6054	    if (check == CUR_PTR) {
6055		xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
6056		            "in xmlParseAttributeListDecl\n");
6057		if (defaultValue != NULL)
6058		    xmlFree(defaultValue);
6059	        if (tree != NULL)
6060		    xmlFreeEnumeration(tree);
6061		break;
6062	    }
6063	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6064		(ctxt->sax->attributeDecl != NULL))
6065		ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6066	                        type, def, defaultValue, tree);
6067	    else if (tree != NULL)
6068		xmlFreeEnumeration(tree);
6069
6070	    if ((ctxt->sax2) && (defaultValue != NULL) &&
6071	        (def != XML_ATTRIBUTE_IMPLIED) &&
6072		(def != XML_ATTRIBUTE_REQUIRED)) {
6073		xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6074	    }
6075	    if (ctxt->sax2) {
6076		xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6077	    }
6078	    if (defaultValue != NULL)
6079	        xmlFree(defaultValue);
6080	    GROW;
6081	}
6082	if (RAW == '>') {
6083	    if (input != ctxt->input) {
6084		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6085    "Attribute list declaration doesn't start and stop in the same entity\n",
6086                                 NULL, NULL);
6087	    }
6088	    NEXT;
6089	}
6090    }
6091}
6092
6093/**
6094 * xmlParseElementMixedContentDecl:
6095 * @ctxt:  an XML parser context
6096 * @inputchk:  the input used for the current entity, needed for boundary checks
6097 *
6098 * parse the declaration for a Mixed Element content
6099 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6100 *
6101 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6102 *                '(' S? '#PCDATA' S? ')'
6103 *
6104 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6105 *
6106 * [ VC: No Duplicate Types ]
6107 * The same name must not appear more than once in a single
6108 * mixed-content declaration.
6109 *
6110 * returns: the list of the xmlElementContentPtr describing the element choices
6111 */
6112xmlElementContentPtr
6113xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6114    xmlElementContentPtr ret = NULL, cur = NULL, n;
6115    const xmlChar *elem = NULL;
6116
6117    GROW;
6118    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6119	SKIP(7);
6120	SKIP_BLANKS;
6121	SHRINK;
6122	if (RAW == ')') {
6123	    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6124		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6125"Element content declaration doesn't start and stop in the same entity\n",
6126                                 NULL, NULL);
6127	    }
6128	    NEXT;
6129	    ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6130	    if (ret == NULL)
6131	        return(NULL);
6132	    if (RAW == '*') {
6133		ret->ocur = XML_ELEMENT_CONTENT_MULT;
6134		NEXT;
6135	    }
6136	    return(ret);
6137	}
6138	if ((RAW == '(') || (RAW == '|')) {
6139	    ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6140	    if (ret == NULL) return(NULL);
6141	}
6142	while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6143	    NEXT;
6144	    if (elem == NULL) {
6145	        ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6146		if (ret == NULL) return(NULL);
6147		ret->c1 = cur;
6148		if (cur != NULL)
6149		    cur->parent = ret;
6150		cur = ret;
6151	    } else {
6152	        n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6153		if (n == NULL) return(NULL);
6154		n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6155		if (n->c1 != NULL)
6156		    n->c1->parent = n;
6157	        cur->c2 = n;
6158		if (n != NULL)
6159		    n->parent = cur;
6160		cur = n;
6161	    }
6162	    SKIP_BLANKS;
6163	    elem = xmlParseName(ctxt);
6164	    if (elem == NULL) {
6165		xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6166			"xmlParseElementMixedContentDecl : Name expected\n");
6167		xmlFreeDocElementContent(ctxt->myDoc, cur);
6168		return(NULL);
6169	    }
6170	    SKIP_BLANKS;
6171	    GROW;
6172	}
6173	if ((RAW == ')') && (NXT(1) == '*')) {
6174	    if (elem != NULL) {
6175		cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6176		                               XML_ELEMENT_CONTENT_ELEMENT);
6177		if (cur->c2 != NULL)
6178		    cur->c2->parent = cur;
6179            }
6180            if (ret != NULL)
6181                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6182	    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6183		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6184"Element content declaration doesn't start and stop in the same entity\n",
6185				 NULL, NULL);
6186	    }
6187	    SKIP(2);
6188	} else {
6189	    xmlFreeDocElementContent(ctxt->myDoc, ret);
6190	    xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6191	    return(NULL);
6192	}
6193
6194    } else {
6195	xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6196    }
6197    return(ret);
6198}
6199
6200/**
6201 * xmlParseElementChildrenContentDeclPriv:
6202 * @ctxt:  an XML parser context
6203 * @inputchk:  the input used for the current entity, needed for boundary checks
6204 * @depth: the level of recursion
6205 *
6206 * parse the declaration for a Mixed Element content
6207 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6208 *
6209 *
6210 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6211 *
6212 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6213 *
6214 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6215 *
6216 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6217 *
6218 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6219 * TODO Parameter-entity replacement text must be properly nested
6220 *	with parenthesized groups. That is to say, if either of the
6221 *	opening or closing parentheses in a choice, seq, or Mixed
6222 *	construct is contained in the replacement text for a parameter
6223 *	entity, both must be contained in the same replacement text. For
6224 *	interoperability, if a parameter-entity reference appears in a
6225 *	choice, seq, or Mixed construct, its replacement text should not
6226 *	be empty, and neither the first nor last non-blank character of
6227 *	the replacement text should be a connector (| or ,).
6228 *
6229 * Returns the tree of xmlElementContentPtr describing the element
6230 *          hierarchy.
6231 */
6232static xmlElementContentPtr
6233xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6234                                       int depth) {
6235    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6236    const xmlChar *elem;
6237    xmlChar type = 0;
6238
6239    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6240        (depth >  2048)) {
6241        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6242"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6243                          depth);
6244	return(NULL);
6245    }
6246    SKIP_BLANKS;
6247    GROW;
6248    if (RAW == '(') {
6249	int inputid = ctxt->input->id;
6250
6251        /* Recurse on first child */
6252	NEXT;
6253	SKIP_BLANKS;
6254        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6255                                                           depth + 1);
6256	SKIP_BLANKS;
6257	GROW;
6258    } else {
6259	elem = xmlParseName(ctxt);
6260	if (elem == NULL) {
6261	    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6262	    return(NULL);
6263	}
6264        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6265	if (cur == NULL) {
6266	    xmlErrMemory(ctxt, NULL);
6267	    return(NULL);
6268	}
6269	GROW;
6270	if (RAW == '?') {
6271	    cur->ocur = XML_ELEMENT_CONTENT_OPT;
6272	    NEXT;
6273	} else if (RAW == '*') {
6274	    cur->ocur = XML_ELEMENT_CONTENT_MULT;
6275	    NEXT;
6276	} else if (RAW == '+') {
6277	    cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6278	    NEXT;
6279	} else {
6280	    cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6281	}
6282	GROW;
6283    }
6284    SKIP_BLANKS;
6285    SHRINK;
6286    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6287        /*
6288	 * Each loop we parse one separator and one element.
6289	 */
6290        if (RAW == ',') {
6291	    if (type == 0) type = CUR;
6292
6293	    /*
6294	     * Detect "Name | Name , Name" error
6295	     */
6296	    else if (type != CUR) {
6297		xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6298		    "xmlParseElementChildrenContentDecl : '%c' expected\n",
6299		                  type);
6300		if ((last != NULL) && (last != ret))
6301		    xmlFreeDocElementContent(ctxt->myDoc, last);
6302		if (ret != NULL)
6303		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6304		return(NULL);
6305	    }
6306	    NEXT;
6307
6308	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6309	    if (op == NULL) {
6310		if ((last != NULL) && (last != ret))
6311		    xmlFreeDocElementContent(ctxt->myDoc, last);
6312	        xmlFreeDocElementContent(ctxt->myDoc, ret);
6313		return(NULL);
6314	    }
6315	    if (last == NULL) {
6316		op->c1 = ret;
6317		if (ret != NULL)
6318		    ret->parent = op;
6319		ret = cur = op;
6320	    } else {
6321	        cur->c2 = op;
6322		if (op != NULL)
6323		    op->parent = cur;
6324		op->c1 = last;
6325		if (last != NULL)
6326		    last->parent = op;
6327		cur =op;
6328		last = NULL;
6329	    }
6330	} else if (RAW == '|') {
6331	    if (type == 0) type = CUR;
6332
6333	    /*
6334	     * Detect "Name , Name | Name" error
6335	     */
6336	    else if (type != CUR) {
6337		xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6338		    "xmlParseElementChildrenContentDecl : '%c' expected\n",
6339				  type);
6340		if ((last != NULL) && (last != ret))
6341		    xmlFreeDocElementContent(ctxt->myDoc, last);
6342		if (ret != NULL)
6343		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6344		return(NULL);
6345	    }
6346	    NEXT;
6347
6348	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6349	    if (op == NULL) {
6350		if ((last != NULL) && (last != ret))
6351		    xmlFreeDocElementContent(ctxt->myDoc, last);
6352		if (ret != NULL)
6353		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6354		return(NULL);
6355	    }
6356	    if (last == NULL) {
6357		op->c1 = ret;
6358		if (ret != NULL)
6359		    ret->parent = op;
6360		ret = cur = op;
6361	    } else {
6362	        cur->c2 = op;
6363		if (op != NULL)
6364		    op->parent = cur;
6365		op->c1 = last;
6366		if (last != NULL)
6367		    last->parent = op;
6368		cur =op;
6369		last = NULL;
6370	    }
6371	} else {
6372	    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6373	    if ((last != NULL) && (last != ret))
6374	        xmlFreeDocElementContent(ctxt->myDoc, last);
6375	    if (ret != NULL)
6376		xmlFreeDocElementContent(ctxt->myDoc, ret);
6377	    return(NULL);
6378	}
6379	GROW;
6380	SKIP_BLANKS;
6381	GROW;
6382	if (RAW == '(') {
6383	    int inputid = ctxt->input->id;
6384	    /* Recurse on second child */
6385	    NEXT;
6386	    SKIP_BLANKS;
6387	    last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6388                                                          depth + 1);
6389	    SKIP_BLANKS;
6390	} else {
6391	    elem = xmlParseName(ctxt);
6392	    if (elem == NULL) {
6393		xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6394		if (ret != NULL)
6395		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6396		return(NULL);
6397	    }
6398	    last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6399	    if (last == NULL) {
6400		if (ret != NULL)
6401		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6402		return(NULL);
6403	    }
6404	    if (RAW == '?') {
6405		last->ocur = XML_ELEMENT_CONTENT_OPT;
6406		NEXT;
6407	    } else if (RAW == '*') {
6408		last->ocur = XML_ELEMENT_CONTENT_MULT;
6409		NEXT;
6410	    } else if (RAW == '+') {
6411		last->ocur = XML_ELEMENT_CONTENT_PLUS;
6412		NEXT;
6413	    } else {
6414		last->ocur = XML_ELEMENT_CONTENT_ONCE;
6415	    }
6416	}
6417	SKIP_BLANKS;
6418	GROW;
6419    }
6420    if ((cur != NULL) && (last != NULL)) {
6421        cur->c2 = last;
6422	if (last != NULL)
6423	    last->parent = cur;
6424    }
6425    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6426	xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6427"Element content declaration doesn't start and stop in the same entity\n",
6428			 NULL, NULL);
6429    }
6430    NEXT;
6431    if (RAW == '?') {
6432	if (ret != NULL) {
6433	    if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6434	        (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6435	        ret->ocur = XML_ELEMENT_CONTENT_MULT;
6436	    else
6437	        ret->ocur = XML_ELEMENT_CONTENT_OPT;
6438	}
6439	NEXT;
6440    } else if (RAW == '*') {
6441	if (ret != NULL) {
6442	    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6443	    cur = ret;
6444	    /*
6445	     * Some normalization:
6446	     * (a | b* | c?)* == (a | b | c)*
6447	     */
6448	    while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6449		if ((cur->c1 != NULL) &&
6450	            ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6451		     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6452		    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6453		if ((cur->c2 != NULL) &&
6454	            ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6455		     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6456		    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6457		cur = cur->c2;
6458	    }
6459	}
6460	NEXT;
6461    } else if (RAW == '+') {
6462	if (ret != NULL) {
6463	    int found = 0;
6464
6465	    if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6466	        (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6467	        ret->ocur = XML_ELEMENT_CONTENT_MULT;
6468	    else
6469	        ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6470	    /*
6471	     * Some normalization:
6472	     * (a | b*)+ == (a | b)*
6473	     * (a | b?)+ == (a | b)*
6474	     */
6475	    while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6476		if ((cur->c1 != NULL) &&
6477	            ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6478		     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6479		    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6480		    found = 1;
6481		}
6482		if ((cur->c2 != NULL) &&
6483	            ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6484		     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6485		    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6486		    found = 1;
6487		}
6488		cur = cur->c2;
6489	    }
6490	    if (found)
6491		ret->ocur = XML_ELEMENT_CONTENT_MULT;
6492	}
6493	NEXT;
6494    }
6495    return(ret);
6496}
6497
6498/**
6499 * xmlParseElementChildrenContentDecl:
6500 * @ctxt:  an XML parser context
6501 * @inputchk:  the input used for the current entity, needed for boundary checks
6502 *
6503 * parse the declaration for a Mixed Element content
6504 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6505 *
6506 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6507 *
6508 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6509 *
6510 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6511 *
6512 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6513 *
6514 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6515 * TODO Parameter-entity replacement text must be properly nested
6516 *	with parenthesized groups. That is to say, if either of the
6517 *	opening or closing parentheses in a choice, seq, or Mixed
6518 *	construct is contained in the replacement text for a parameter
6519 *	entity, both must be contained in the same replacement text. For
6520 *	interoperability, if a parameter-entity reference appears in a
6521 *	choice, seq, or Mixed construct, its replacement text should not
6522 *	be empty, and neither the first nor last non-blank character of
6523 *	the replacement text should be a connector (| or ,).
6524 *
6525 * Returns the tree of xmlElementContentPtr describing the element
6526 *          hierarchy.
6527 */
6528xmlElementContentPtr
6529xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6530    /* stub left for API/ABI compat */
6531    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6532}
6533
6534/**
6535 * xmlParseElementContentDecl:
6536 * @ctxt:  an XML parser context
6537 * @name:  the name of the element being defined.
6538 * @result:  the Element Content pointer will be stored here if any
6539 *
6540 * parse the declaration for an Element content either Mixed or Children,
6541 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6542 *
6543 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6544 *
6545 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6546 */
6547
6548int
6549xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6550                           xmlElementContentPtr *result) {
6551
6552    xmlElementContentPtr tree = NULL;
6553    int inputid = ctxt->input->id;
6554    int res;
6555
6556    *result = NULL;
6557
6558    if (RAW != '(') {
6559	xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6560		"xmlParseElementContentDecl : %s '(' expected\n", name);
6561	return(-1);
6562    }
6563    NEXT;
6564    GROW;
6565    if (ctxt->instate == XML_PARSER_EOF)
6566        return(-1);
6567    SKIP_BLANKS;
6568    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6569        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6570	res = XML_ELEMENT_TYPE_MIXED;
6571    } else {
6572        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6573	res = XML_ELEMENT_TYPE_ELEMENT;
6574    }
6575    SKIP_BLANKS;
6576    *result = tree;
6577    return(res);
6578}
6579
6580/**
6581 * xmlParseElementDecl:
6582 * @ctxt:  an XML parser context
6583 *
6584 * parse an Element declaration.
6585 *
6586 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6587 *
6588 * [ VC: Unique Element Type Declaration ]
6589 * No element type may be declared more than once
6590 *
6591 * Returns the type of the element, or -1 in case of error
6592 */
6593int
6594xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6595    const xmlChar *name;
6596    int ret = -1;
6597    xmlElementContentPtr content  = NULL;
6598
6599    /* GROW; done in the caller */
6600    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6601	xmlParserInputPtr input = ctxt->input;
6602
6603	SKIP(9);
6604	if (!IS_BLANK_CH(CUR)) {
6605	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6606		           "Space required after 'ELEMENT'\n");
6607	}
6608        SKIP_BLANKS;
6609        name = xmlParseName(ctxt);
6610	if (name == NULL) {
6611	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6612			   "xmlParseElementDecl: no name for Element\n");
6613	    return(-1);
6614	}
6615	while ((RAW == 0) && (ctxt->inputNr > 1))
6616	    xmlPopInput(ctxt);
6617	if (!IS_BLANK_CH(CUR)) {
6618	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6619			   "Space required after the element name\n");
6620	}
6621        SKIP_BLANKS;
6622	if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6623	    SKIP(5);
6624	    /*
6625	     * Element must always be empty.
6626	     */
6627	    ret = XML_ELEMENT_TYPE_EMPTY;
6628	} else if ((RAW == 'A') && (NXT(1) == 'N') &&
6629	           (NXT(2) == 'Y')) {
6630	    SKIP(3);
6631	    /*
6632	     * Element is a generic container.
6633	     */
6634	    ret = XML_ELEMENT_TYPE_ANY;
6635	} else if (RAW == '(') {
6636	    ret = xmlParseElementContentDecl(ctxt, name, &content);
6637	} else {
6638	    /*
6639	     * [ WFC: PEs in Internal Subset ] error handling.
6640	     */
6641	    if ((RAW == '%') && (ctxt->external == 0) &&
6642	        (ctxt->inputNr == 1)) {
6643		xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6644	  "PEReference: forbidden within markup decl in internal subset\n");
6645	    } else {
6646		xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6647		      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6648            }
6649	    return(-1);
6650	}
6651
6652	SKIP_BLANKS;
6653	/*
6654	 * Pop-up of finished entities.
6655	 */
6656	while ((RAW == 0) && (ctxt->inputNr > 1))
6657	    xmlPopInput(ctxt);
6658	SKIP_BLANKS;
6659
6660	if (RAW != '>') {
6661	    xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6662	    if (content != NULL) {
6663		xmlFreeDocElementContent(ctxt->myDoc, content);
6664	    }
6665	} else {
6666	    if (input != ctxt->input) {
6667		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6668    "Element declaration doesn't start and stop in the same entity\n");
6669	    }
6670
6671	    NEXT;
6672	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6673		(ctxt->sax->elementDecl != NULL)) {
6674		if (content != NULL)
6675		    content->parent = NULL;
6676	        ctxt->sax->elementDecl(ctxt->userData, name, ret,
6677		                       content);
6678		if ((content != NULL) && (content->parent == NULL)) {
6679		    /*
6680		     * this is a trick: if xmlAddElementDecl is called,
6681		     * instead of copying the full tree it is plugged directly
6682		     * if called from the parser. Avoid duplicating the
6683		     * interfaces or change the API/ABI
6684		     */
6685		    xmlFreeDocElementContent(ctxt->myDoc, content);
6686		}
6687	    } else if (content != NULL) {
6688		xmlFreeDocElementContent(ctxt->myDoc, content);
6689	    }
6690	}
6691    }
6692    return(ret);
6693}
6694
6695/**
6696 * xmlParseConditionalSections
6697 * @ctxt:  an XML parser context
6698 *
6699 * [61] conditionalSect ::= includeSect | ignoreSect
6700 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6701 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6702 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6703 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6704 */
6705
6706static void
6707xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6708    int id = ctxt->input->id;
6709
6710    SKIP(3);
6711    SKIP_BLANKS;
6712    if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6713	SKIP(7);
6714	SKIP_BLANKS;
6715	if (RAW != '[') {
6716	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6717	} else {
6718	    if (ctxt->input->id != id) {
6719		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6720	    "All markup of the conditional section is not in the same entity\n",
6721				     NULL, NULL);
6722	    }
6723	    NEXT;
6724	}
6725	if (xmlParserDebugEntities) {
6726	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6727		xmlGenericError(xmlGenericErrorContext,
6728			"%s(%d): ", ctxt->input->filename,
6729			ctxt->input->line);
6730	    xmlGenericError(xmlGenericErrorContext,
6731		    "Entering INCLUDE Conditional Section\n");
6732	}
6733
6734	while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
6735	        (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
6736	    const xmlChar *check = CUR_PTR;
6737	    unsigned int cons = ctxt->input->consumed;
6738
6739	    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6740		xmlParseConditionalSections(ctxt);
6741	    } else if (IS_BLANK_CH(CUR)) {
6742		NEXT;
6743	    } else if (RAW == '%') {
6744		xmlParsePEReference(ctxt);
6745	    } else
6746		xmlParseMarkupDecl(ctxt);
6747
6748	    /*
6749	     * Pop-up of finished entities.
6750	     */
6751	    while ((RAW == 0) && (ctxt->inputNr > 1))
6752		xmlPopInput(ctxt);
6753
6754	    if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
6755		xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6756		break;
6757	    }
6758	}
6759	if (xmlParserDebugEntities) {
6760	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6761		xmlGenericError(xmlGenericErrorContext,
6762			"%s(%d): ", ctxt->input->filename,
6763			ctxt->input->line);
6764	    xmlGenericError(xmlGenericErrorContext,
6765		    "Leaving INCLUDE Conditional Section\n");
6766	}
6767
6768    } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6769	int state;
6770	xmlParserInputState instate;
6771	int depth = 0;
6772
6773	SKIP(6);
6774	SKIP_BLANKS;
6775	if (RAW != '[') {
6776	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6777	} else {
6778	    if (ctxt->input->id != id) {
6779		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6780	    "All markup of the conditional section is not in the same entity\n",
6781				     NULL, NULL);
6782	    }
6783	    NEXT;
6784	}
6785	if (xmlParserDebugEntities) {
6786	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6787		xmlGenericError(xmlGenericErrorContext,
6788			"%s(%d): ", ctxt->input->filename,
6789			ctxt->input->line);
6790	    xmlGenericError(xmlGenericErrorContext,
6791		    "Entering IGNORE Conditional Section\n");
6792	}
6793
6794	/*
6795	 * Parse up to the end of the conditional section
6796	 * But disable SAX event generating DTD building in the meantime
6797	 */
6798	state = ctxt->disableSAX;
6799	instate = ctxt->instate;
6800	if (ctxt->recovery == 0) ctxt->disableSAX = 1;
6801	ctxt->instate = XML_PARSER_IGNORE;
6802
6803	while (((depth >= 0) && (RAW != 0)) &&
6804               (ctxt->instate != XML_PARSER_EOF)) {
6805	  if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6806	    depth++;
6807	    SKIP(3);
6808	    continue;
6809	  }
6810	  if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6811	    if (--depth >= 0) SKIP(3);
6812	    continue;
6813	  }
6814	  NEXT;
6815	  continue;
6816	}
6817
6818	ctxt->disableSAX = state;
6819	ctxt->instate = instate;
6820
6821	if (xmlParserDebugEntities) {
6822	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6823		xmlGenericError(xmlGenericErrorContext,
6824			"%s(%d): ", ctxt->input->filename,
6825			ctxt->input->line);
6826	    xmlGenericError(xmlGenericErrorContext,
6827		    "Leaving IGNORE Conditional Section\n");
6828	}
6829
6830    } else {
6831	xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6832    }
6833
6834    if (RAW == 0)
6835        SHRINK;
6836
6837    if (RAW == 0) {
6838	xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6839    } else {
6840	if (ctxt->input->id != id) {
6841	    xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6842	"All markup of the conditional section is not in the same entity\n",
6843				 NULL, NULL);
6844	}
6845        SKIP(3);
6846    }
6847}
6848
6849/**
6850 * xmlParseMarkupDecl:
6851 * @ctxt:  an XML parser context
6852 *
6853 * parse Markup declarations
6854 *
6855 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6856 *                     NotationDecl | PI | Comment
6857 *
6858 * [ VC: Proper Declaration/PE Nesting ]
6859 * Parameter-entity replacement text must be properly nested with
6860 * markup declarations. That is to say, if either the first character
6861 * or the last character of a markup declaration (markupdecl above) is
6862 * contained in the replacement text for a parameter-entity reference,
6863 * both must be contained in the same replacement text.
6864 *
6865 * [ WFC: PEs in Internal Subset ]
6866 * In the internal DTD subset, parameter-entity references can occur
6867 * only where markup declarations can occur, not within markup declarations.
6868 * (This does not apply to references that occur in external parameter
6869 * entities or to the external subset.)
6870 */
6871void
6872xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6873    GROW;
6874    if (CUR == '<') {
6875        if (NXT(1) == '!') {
6876	    switch (NXT(2)) {
6877	        case 'E':
6878		    if (NXT(3) == 'L')
6879			xmlParseElementDecl(ctxt);
6880		    else if (NXT(3) == 'N')
6881			xmlParseEntityDecl(ctxt);
6882		    break;
6883	        case 'A':
6884		    xmlParseAttributeListDecl(ctxt);
6885		    break;
6886	        case 'N':
6887		    xmlParseNotationDecl(ctxt);
6888		    break;
6889	        case '-':
6890		    xmlParseComment(ctxt);
6891		    break;
6892		default:
6893		    /* there is an error but it will be detected later */
6894		    break;
6895	    }
6896	} else if (NXT(1) == '?') {
6897	    xmlParsePI(ctxt);
6898	}
6899    }
6900    /*
6901     * This is only for internal subset. On external entities,
6902     * the replacement is done before parsing stage
6903     */
6904    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
6905	xmlParsePEReference(ctxt);
6906
6907    /*
6908     * Conditional sections are allowed from entities included
6909     * by PE References in the internal subset.
6910     */
6911    if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
6912        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6913	    xmlParseConditionalSections(ctxt);
6914	}
6915    }
6916
6917    ctxt->instate = XML_PARSER_DTD;
6918}
6919
6920/**
6921 * xmlParseTextDecl:
6922 * @ctxt:  an XML parser context
6923 *
6924 * parse an XML declaration header for external entities
6925 *
6926 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
6927 */
6928
6929void
6930xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
6931    xmlChar *version;
6932    const xmlChar *encoding;
6933
6934    /*
6935     * We know that '<?xml' is here.
6936     */
6937    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
6938	SKIP(5);
6939    } else {
6940	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
6941	return;
6942    }
6943
6944    if (!IS_BLANK_CH(CUR)) {
6945	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6946		       "Space needed after '<?xml'\n");
6947    }
6948    SKIP_BLANKS;
6949
6950    /*
6951     * We may have the VersionInfo here.
6952     */
6953    version = xmlParseVersionInfo(ctxt);
6954    if (version == NULL)
6955	version = xmlCharStrdup(XML_DEFAULT_VERSION);
6956    else {
6957	if (!IS_BLANK_CH(CUR)) {
6958	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6959		           "Space needed here\n");
6960	}
6961    }
6962    ctxt->input->version = version;
6963
6964    /*
6965     * We must have the encoding declaration
6966     */
6967    encoding = xmlParseEncodingDecl(ctxt);
6968    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
6969	/*
6970	 * The XML REC instructs us to stop parsing right here
6971	 */
6972        return;
6973    }
6974    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
6975	xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
6976		       "Missing encoding in text declaration\n");
6977    }
6978
6979    SKIP_BLANKS;
6980    if ((RAW == '?') && (NXT(1) == '>')) {
6981        SKIP(2);
6982    } else if (RAW == '>') {
6983        /* Deprecated old WD ... */
6984	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
6985	NEXT;
6986    } else {
6987	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
6988	MOVETO_ENDTAG(CUR_PTR);
6989	NEXT;
6990    }
6991}
6992
6993/**
6994 * xmlParseExternalSubset:
6995 * @ctxt:  an XML parser context
6996 * @ExternalID: the external identifier
6997 * @SystemID: the system identifier (or URL)
6998 *
6999 * parse Markup declarations from an external subset
7000 *
7001 * [30] extSubset ::= textDecl? extSubsetDecl
7002 *
7003 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7004 */
7005void
7006xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7007                       const xmlChar *SystemID) {
7008    xmlDetectSAX2(ctxt);
7009    GROW;
7010
7011    if ((ctxt->encoding == NULL) &&
7012        (ctxt->input->end - ctxt->input->cur >= 4)) {
7013        xmlChar start[4];
7014	xmlCharEncoding enc;
7015
7016	start[0] = RAW;
7017	start[1] = NXT(1);
7018	start[2] = NXT(2);
7019	start[3] = NXT(3);
7020	enc = xmlDetectCharEncoding(start, 4);
7021	if (enc != XML_CHAR_ENCODING_NONE)
7022	    xmlSwitchEncoding(ctxt, enc);
7023    }
7024
7025    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7026	xmlParseTextDecl(ctxt);
7027	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7028	    /*
7029	     * The XML REC instructs us to stop parsing right here
7030	     */
7031	    ctxt->instate = XML_PARSER_EOF;
7032	    return;
7033	}
7034    }
7035    if (ctxt->myDoc == NULL) {
7036        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7037	if (ctxt->myDoc == NULL) {
7038	    xmlErrMemory(ctxt, "New Doc failed");
7039	    return;
7040	}
7041	ctxt->myDoc->properties = XML_DOC_INTERNAL;
7042    }
7043    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7044        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7045
7046    ctxt->instate = XML_PARSER_DTD;
7047    ctxt->external = 1;
7048    while (((RAW == '<') && (NXT(1) == '?')) ||
7049           ((RAW == '<') && (NXT(1) == '!')) ||
7050	   (RAW == '%') || IS_BLANK_CH(CUR)) {
7051	const xmlChar *check = CUR_PTR;
7052	unsigned int cons = ctxt->input->consumed;
7053
7054	GROW;
7055        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7056	    xmlParseConditionalSections(ctxt);
7057	} else if (IS_BLANK_CH(CUR)) {
7058	    NEXT;
7059	} else if (RAW == '%') {
7060            xmlParsePEReference(ctxt);
7061	} else
7062	    xmlParseMarkupDecl(ctxt);
7063
7064	/*
7065	 * Pop-up of finished entities.
7066	 */
7067	while ((RAW == 0) && (ctxt->inputNr > 1))
7068	    xmlPopInput(ctxt);
7069
7070	if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
7071	    xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7072	    break;
7073	}
7074    }
7075
7076    if (RAW != 0) {
7077	xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7078    }
7079
7080}
7081
7082/**
7083 * xmlParseReference:
7084 * @ctxt:  an XML parser context
7085 *
7086 * parse and handle entity references in content, depending on the SAX
7087 * interface, this may end-up in a call to character() if this is a
7088 * CharRef, a predefined entity, if there is no reference() callback.
7089 * or if the parser was asked to switch to that mode.
7090 *
7091 * [67] Reference ::= EntityRef | CharRef
7092 */
7093void
7094xmlParseReference(xmlParserCtxtPtr ctxt) {
7095    xmlEntityPtr ent;
7096    xmlChar *val;
7097    int was_checked;
7098    xmlNodePtr list = NULL;
7099    xmlParserErrors ret = XML_ERR_OK;
7100
7101
7102    if (RAW != '&')
7103        return;
7104
7105    /*
7106     * Simple case of a CharRef
7107     */
7108    if (NXT(1) == '#') {
7109	int i = 0;
7110	xmlChar out[10];
7111	int hex = NXT(2);
7112	int value = xmlParseCharRef(ctxt);
7113
7114	if (value == 0)
7115	    return;
7116	if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
7117	    /*
7118	     * So we are using non-UTF-8 buffers
7119	     * Check that the char fit on 8bits, if not
7120	     * generate a CharRef.
7121	     */
7122	    if (value <= 0xFF) {
7123		out[0] = value;
7124		out[1] = 0;
7125		if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7126		    (!ctxt->disableSAX))
7127		    ctxt->sax->characters(ctxt->userData, out, 1);
7128	    } else {
7129		if ((hex == 'x') || (hex == 'X'))
7130		    snprintf((char *)out, sizeof(out), "#x%X", value);
7131		else
7132		    snprintf((char *)out, sizeof(out), "#%d", value);
7133		if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7134		    (!ctxt->disableSAX))
7135		    ctxt->sax->reference(ctxt->userData, out);
7136	    }
7137	} else {
7138	    /*
7139	     * Just encode the value in UTF-8
7140	     */
7141	    COPY_BUF(0 ,out, i, value);
7142	    out[i] = 0;
7143	    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7144		(!ctxt->disableSAX))
7145		ctxt->sax->characters(ctxt->userData, out, i);
7146	}
7147	return;
7148    }
7149
7150    /*
7151     * We are seeing an entity reference
7152     */
7153    ent = xmlParseEntityRef(ctxt);
7154    if (ent == NULL) return;
7155    if (!ctxt->wellFormed)
7156	return;
7157    was_checked = ent->checked;
7158
7159    /* special case of predefined entities */
7160    if ((ent->name == NULL) ||
7161        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7162	val = ent->content;
7163	if (val == NULL) return;
7164	/*
7165	 * inline the entity.
7166	 */
7167	if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7168	    (!ctxt->disableSAX))
7169	    ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7170	return;
7171    }
7172
7173    /*
7174     * The first reference to the entity trigger a parsing phase
7175     * where the ent->children is filled with the result from
7176     * the parsing.
7177     * Note: external parsed entities will not be loaded, it is not
7178     * required for a non-validating parser, unless the parsing option
7179     * of validating, or substituting entities were given. Doing so is
7180     * far more secure as the parser will only process data coming from
7181     * the document entity by default.
7182     */
7183    if ((ent->checked == 0) &&
7184        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7185         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7186	unsigned long oldnbent = ctxt->nbentities;
7187
7188	/*
7189	 * This is a bit hackish but this seems the best
7190	 * way to make sure both SAX and DOM entity support
7191	 * behaves okay.
7192	 */
7193	void *user_data;
7194	if (ctxt->userData == ctxt)
7195	    user_data = NULL;
7196	else
7197	    user_data = ctxt->userData;
7198
7199	/*
7200	 * Check that this entity is well formed
7201	 * 4.3.2: An internal general parsed entity is well-formed
7202	 * if its replacement text matches the production labeled
7203	 * content.
7204	 */
7205	if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7206	    ctxt->depth++;
7207	    ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7208	                                              user_data, &list);
7209	    ctxt->depth--;
7210
7211	} else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7212	    ctxt->depth++;
7213	    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7214	                                   user_data, ctxt->depth, ent->URI,
7215					   ent->ExternalID, &list);
7216	    ctxt->depth--;
7217	} else {
7218	    ret = XML_ERR_ENTITY_PE_INTERNAL;
7219	    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7220			 "invalid entity type found\n", NULL);
7221	}
7222
7223	/*
7224	 * Store the number of entities needing parsing for this entity
7225	 * content and do checkings
7226	 */
7227	ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
7228	if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7229	    ent->checked |= 1;
7230	if (ret == XML_ERR_ENTITY_LOOP) {
7231	    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7232	    xmlFreeNodeList(list);
7233	    return;
7234	}
7235	if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
7236	    xmlFreeNodeList(list);
7237	    return;
7238	}
7239
7240	if ((ret == XML_ERR_OK) && (list != NULL)) {
7241	    if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
7242	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
7243		(ent->children == NULL)) {
7244		ent->children = list;
7245		if (ctxt->replaceEntities) {
7246		    /*
7247		     * Prune it directly in the generated document
7248		     * except for single text nodes.
7249		     */
7250		    if (((list->type == XML_TEXT_NODE) &&
7251			 (list->next == NULL)) ||
7252			(ctxt->parseMode == XML_PARSE_READER)) {
7253			list->parent = (xmlNodePtr) ent;
7254			list = NULL;
7255			ent->owner = 1;
7256		    } else {
7257			ent->owner = 0;
7258			while (list != NULL) {
7259			    list->parent = (xmlNodePtr) ctxt->node;
7260			    list->doc = ctxt->myDoc;
7261			    if (list->next == NULL)
7262				ent->last = list;
7263			    list = list->next;
7264			}
7265			list = ent->children;
7266#ifdef LIBXML_LEGACY_ENABLED
7267			if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7268			  xmlAddEntityReference(ent, list, NULL);
7269#endif /* LIBXML_LEGACY_ENABLED */
7270		    }
7271		} else {
7272		    ent->owner = 1;
7273		    while (list != NULL) {
7274			list->parent = (xmlNodePtr) ent;
7275			xmlSetTreeDoc(list, ent->doc);
7276			if (list->next == NULL)
7277			    ent->last = list;
7278			list = list->next;
7279		    }
7280		}
7281	    } else {
7282		xmlFreeNodeList(list);
7283		list = NULL;
7284	    }
7285	} else if ((ret != XML_ERR_OK) &&
7286		   (ret != XML_WAR_UNDECLARED_ENTITY)) {
7287	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7288		     "Entity '%s' failed to parse\n", ent->name);
7289	} else if (list != NULL) {
7290	    xmlFreeNodeList(list);
7291	    list = NULL;
7292	}
7293	if (ent->checked == 0)
7294	    ent->checked = 2;
7295    } else if (ent->checked != 1) {
7296	ctxt->nbentities += ent->checked / 2;
7297    }
7298
7299    /*
7300     * Now that the entity content has been gathered
7301     * provide it to the application, this can take different forms based
7302     * on the parsing modes.
7303     */
7304    if (ent->children == NULL) {
7305	/*
7306	 * Probably running in SAX mode and the callbacks don't
7307	 * build the entity content. So unless we already went
7308	 * though parsing for first checking go though the entity
7309	 * content to generate callbacks associated to the entity
7310	 */
7311	if (was_checked != 0) {
7312	    void *user_data;
7313	    /*
7314	     * This is a bit hackish but this seems the best
7315	     * way to make sure both SAX and DOM entity support
7316	     * behaves okay.
7317	     */
7318	    if (ctxt->userData == ctxt)
7319		user_data = NULL;
7320	    else
7321		user_data = ctxt->userData;
7322
7323	    if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7324		ctxt->depth++;
7325		ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7326				   ent->content, user_data, NULL);
7327		ctxt->depth--;
7328	    } else if (ent->etype ==
7329		       XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7330		ctxt->depth++;
7331		ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7332			   ctxt->sax, user_data, ctxt->depth,
7333			   ent->URI, ent->ExternalID, NULL);
7334		ctxt->depth--;
7335	    } else {
7336		ret = XML_ERR_ENTITY_PE_INTERNAL;
7337		xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7338			     "invalid entity type found\n", NULL);
7339	    }
7340	    if (ret == XML_ERR_ENTITY_LOOP) {
7341		xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7342		return;
7343	    }
7344	}
7345	if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7346	    (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7347	    /*
7348	     * Entity reference callback comes second, it's somewhat
7349	     * superfluous but a compatibility to historical behaviour
7350	     */
7351	    ctxt->sax->reference(ctxt->userData, ent->name);
7352	}
7353	return;
7354    }
7355
7356    /*
7357     * If we didn't get any children for the entity being built
7358     */
7359    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7360	(ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7361	/*
7362	 * Create a node.
7363	 */
7364	ctxt->sax->reference(ctxt->userData, ent->name);
7365	return;
7366    }
7367
7368    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
7369	/*
7370	 * There is a problem on the handling of _private for entities
7371	 * (bug 155816): Should we copy the content of the field from
7372	 * the entity (possibly overwriting some value set by the user
7373	 * when a copy is created), should we leave it alone, or should
7374	 * we try to take care of different situations?  The problem
7375	 * is exacerbated by the usage of this field by the xmlReader.
7376	 * To fix this bug, we look at _private on the created node
7377	 * and, if it's NULL, we copy in whatever was in the entity.
7378	 * If it's not NULL we leave it alone.  This is somewhat of a
7379	 * hack - maybe we should have further tests to determine
7380	 * what to do.
7381	 */
7382	if ((ctxt->node != NULL) && (ent->children != NULL)) {
7383	    /*
7384	     * Seems we are generating the DOM content, do
7385	     * a simple tree copy for all references except the first
7386	     * In the first occurrence list contains the replacement.
7387	     */
7388	    if (((list == NULL) && (ent->owner == 0)) ||
7389		(ctxt->parseMode == XML_PARSE_READER)) {
7390		xmlNodePtr nw = NULL, cur, firstChild = NULL;
7391
7392		/*
7393		 * We are copying here, make sure there is no abuse
7394		 */
7395		ctxt->sizeentcopy += ent->length;
7396		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7397		    return;
7398
7399		/*
7400		 * when operating on a reader, the entities definitions
7401		 * are always owning the entities subtree.
7402		if (ctxt->parseMode == XML_PARSE_READER)
7403		    ent->owner = 1;
7404		 */
7405
7406		cur = ent->children;
7407		while (cur != NULL) {
7408		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7409		    if (nw != NULL) {
7410			if (nw->_private == NULL)
7411			    nw->_private = cur->_private;
7412			if (firstChild == NULL){
7413			    firstChild = nw;
7414			}
7415			nw = xmlAddChild(ctxt->node, nw);
7416		    }
7417		    if (cur == ent->last) {
7418			/*
7419			 * needed to detect some strange empty
7420			 * node cases in the reader tests
7421			 */
7422			if ((ctxt->parseMode == XML_PARSE_READER) &&
7423			    (nw != NULL) &&
7424			    (nw->type == XML_ELEMENT_NODE) &&
7425			    (nw->children == NULL))
7426			    nw->extra = 1;
7427
7428			break;
7429		    }
7430		    cur = cur->next;
7431		}
7432#ifdef LIBXML_LEGACY_ENABLED
7433		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7434		  xmlAddEntityReference(ent, firstChild, nw);
7435#endif /* LIBXML_LEGACY_ENABLED */
7436	    } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7437		xmlNodePtr nw = NULL, cur, next, last,
7438			   firstChild = NULL;
7439
7440		/*
7441		 * We are copying here, make sure there is no abuse
7442		 */
7443		ctxt->sizeentcopy += ent->length;
7444		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7445		    return;
7446
7447		/*
7448		 * Copy the entity child list and make it the new
7449		 * entity child list. The goal is to make sure any
7450		 * ID or REF referenced will be the one from the
7451		 * document content and not the entity copy.
7452		 */
7453		cur = ent->children;
7454		ent->children = NULL;
7455		last = ent->last;
7456		ent->last = NULL;
7457		while (cur != NULL) {
7458		    next = cur->next;
7459		    cur->next = NULL;
7460		    cur->parent = NULL;
7461		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7462		    if (nw != NULL) {
7463			if (nw->_private == NULL)
7464			    nw->_private = cur->_private;
7465			if (firstChild == NULL){
7466			    firstChild = cur;
7467			}
7468			xmlAddChild((xmlNodePtr) ent, nw);
7469			xmlAddChild(ctxt->node, cur);
7470		    }
7471		    if (cur == last)
7472			break;
7473		    cur = next;
7474		}
7475		if (ent->owner == 0)
7476		    ent->owner = 1;
7477#ifdef LIBXML_LEGACY_ENABLED
7478		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7479		  xmlAddEntityReference(ent, firstChild, nw);
7480#endif /* LIBXML_LEGACY_ENABLED */
7481	    } else {
7482		const xmlChar *nbktext;
7483
7484		/*
7485		 * the name change is to avoid coalescing of the
7486		 * node with a possible previous text one which
7487		 * would make ent->children a dangling pointer
7488		 */
7489		nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7490					-1);
7491		if (ent->children->type == XML_TEXT_NODE)
7492		    ent->children->name = nbktext;
7493		if ((ent->last != ent->children) &&
7494		    (ent->last->type == XML_TEXT_NODE))
7495		    ent->last->name = nbktext;
7496		xmlAddChildList(ctxt->node, ent->children);
7497	    }
7498
7499	    /*
7500	     * This is to avoid a nasty side effect, see
7501	     * characters() in SAX.c
7502	     */
7503	    ctxt->nodemem = 0;
7504	    ctxt->nodelen = 0;
7505	    return;
7506	}
7507    }
7508}
7509
7510/**
7511 * xmlParseEntityRef:
7512 * @ctxt:  an XML parser context
7513 *
7514 * parse ENTITY references declarations
7515 *
7516 * [68] EntityRef ::= '&' Name ';'
7517 *
7518 * [ WFC: Entity Declared ]
7519 * In a document without any DTD, a document with only an internal DTD
7520 * subset which contains no parameter entity references, or a document
7521 * with "standalone='yes'", the Name given in the entity reference
7522 * must match that in an entity declaration, except that well-formed
7523 * documents need not declare any of the following entities: amp, lt,
7524 * gt, apos, quot.  The declaration of a parameter entity must precede
7525 * any reference to it.  Similarly, the declaration of a general entity
7526 * must precede any reference to it which appears in a default value in an
7527 * attribute-list declaration. Note that if entities are declared in the
7528 * external subset or in external parameter entities, a non-validating
7529 * processor is not obligated to read and process their declarations;
7530 * for such documents, the rule that an entity must be declared is a
7531 * well-formedness constraint only if standalone='yes'.
7532 *
7533 * [ WFC: Parsed Entity ]
7534 * An entity reference must not contain the name of an unparsed entity
7535 *
7536 * Returns the xmlEntityPtr if found, or NULL otherwise.
7537 */
7538xmlEntityPtr
7539xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7540    const xmlChar *name;
7541    xmlEntityPtr ent = NULL;
7542
7543    GROW;
7544    if (ctxt->instate == XML_PARSER_EOF)
7545        return(NULL);
7546
7547    if (RAW != '&')
7548        return(NULL);
7549    NEXT;
7550    name = xmlParseName(ctxt);
7551    if (name == NULL) {
7552	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7553		       "xmlParseEntityRef: no name\n");
7554        return(NULL);
7555    }
7556    if (RAW != ';') {
7557	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7558	return(NULL);
7559    }
7560    NEXT;
7561
7562    /*
7563     * Predefined entities override any extra definition
7564     */
7565    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7566        ent = xmlGetPredefinedEntity(name);
7567        if (ent != NULL)
7568            return(ent);
7569    }
7570
7571    /*
7572     * Increase the number of entity references parsed
7573     */
7574    ctxt->nbentities++;
7575
7576    /*
7577     * Ask first SAX for entity resolution, otherwise try the
7578     * entities which may have stored in the parser context.
7579     */
7580    if (ctxt->sax != NULL) {
7581	if (ctxt->sax->getEntity != NULL)
7582	    ent = ctxt->sax->getEntity(ctxt->userData, name);
7583	if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7584	    (ctxt->options & XML_PARSE_OLDSAX))
7585	    ent = xmlGetPredefinedEntity(name);
7586	if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7587	    (ctxt->userData==ctxt)) {
7588	    ent = xmlSAX2GetEntity(ctxt, name);
7589	}
7590    }
7591    if (ctxt->instate == XML_PARSER_EOF)
7592	return(NULL);
7593    /*
7594     * [ WFC: Entity Declared ]
7595     * In a document without any DTD, a document with only an
7596     * internal DTD subset which contains no parameter entity
7597     * references, or a document with "standalone='yes'", the
7598     * Name given in the entity reference must match that in an
7599     * entity declaration, except that well-formed documents
7600     * need not declare any of the following entities: amp, lt,
7601     * gt, apos, quot.
7602     * The declaration of a parameter entity must precede any
7603     * reference to it.
7604     * Similarly, the declaration of a general entity must
7605     * precede any reference to it which appears in a default
7606     * value in an attribute-list declaration. Note that if
7607     * entities are declared in the external subset or in
7608     * external parameter entities, a non-validating processor
7609     * is not obligated to read and process their declarations;
7610     * for such documents, the rule that an entity must be
7611     * declared is a well-formedness constraint only if
7612     * standalone='yes'.
7613     */
7614    if (ent == NULL) {
7615	if ((ctxt->standalone == 1) ||
7616	    ((ctxt->hasExternalSubset == 0) &&
7617	     (ctxt->hasPErefs == 0))) {
7618	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7619		     "Entity '%s' not defined\n", name);
7620	} else {
7621	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7622		     "Entity '%s' not defined\n", name);
7623	    if ((ctxt->inSubset == 0) &&
7624		(ctxt->sax != NULL) &&
7625		(ctxt->sax->reference != NULL)) {
7626		ctxt->sax->reference(ctxt->userData, name);
7627	    }
7628	}
7629	ctxt->valid = 0;
7630    }
7631
7632    /*
7633     * [ WFC: Parsed Entity ]
7634     * An entity reference must not contain the name of an
7635     * unparsed entity
7636     */
7637    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7638	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7639		 "Entity reference to unparsed entity %s\n", name);
7640    }
7641
7642    /*
7643     * [ WFC: No External Entity References ]
7644     * Attribute values cannot contain direct or indirect
7645     * entity references to external entities.
7646     */
7647    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7648	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7649	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7650	     "Attribute references external entity '%s'\n", name);
7651    }
7652    /*
7653     * [ WFC: No < in Attribute Values ]
7654     * The replacement text of any entity referred to directly or
7655     * indirectly in an attribute value (other than "&lt;") must
7656     * not contain a <.
7657     */
7658    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7659	     (ent != NULL) &&
7660	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7661	if ((ent->checked & 1) || ((ent->checked == 0) &&
7662	     (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) {
7663	    xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7664	"'<' in entity '%s' is not allowed in attributes values\n", name);
7665        }
7666    }
7667
7668    /*
7669     * Internal check, no parameter entities here ...
7670     */
7671    else {
7672	switch (ent->etype) {
7673	    case XML_INTERNAL_PARAMETER_ENTITY:
7674	    case XML_EXTERNAL_PARAMETER_ENTITY:
7675	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7676	     "Attempt to reference the parameter entity '%s'\n",
7677			      name);
7678	    break;
7679	    default:
7680	    break;
7681	}
7682    }
7683
7684    /*
7685     * [ WFC: No Recursion ]
7686     * A parsed entity must not contain a recursive reference
7687     * to itself, either directly or indirectly.
7688     * Done somewhere else
7689     */
7690    return(ent);
7691}
7692
7693/**
7694 * xmlParseStringEntityRef:
7695 * @ctxt:  an XML parser context
7696 * @str:  a pointer to an index in the string
7697 *
7698 * parse ENTITY references declarations, but this version parses it from
7699 * a string value.
7700 *
7701 * [68] EntityRef ::= '&' Name ';'
7702 *
7703 * [ WFC: Entity Declared ]
7704 * In a document without any DTD, a document with only an internal DTD
7705 * subset which contains no parameter entity references, or a document
7706 * with "standalone='yes'", the Name given in the entity reference
7707 * must match that in an entity declaration, except that well-formed
7708 * documents need not declare any of the following entities: amp, lt,
7709 * gt, apos, quot.  The declaration of a parameter entity must precede
7710 * any reference to it.  Similarly, the declaration of a general entity
7711 * must precede any reference to it which appears in a default value in an
7712 * attribute-list declaration. Note that if entities are declared in the
7713 * external subset or in external parameter entities, a non-validating
7714 * processor is not obligated to read and process their declarations;
7715 * for such documents, the rule that an entity must be declared is a
7716 * well-formedness constraint only if standalone='yes'.
7717 *
7718 * [ WFC: Parsed Entity ]
7719 * An entity reference must not contain the name of an unparsed entity
7720 *
7721 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7722 * is updated to the current location in the string.
7723 */
7724static xmlEntityPtr
7725xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7726    xmlChar *name;
7727    const xmlChar *ptr;
7728    xmlChar cur;
7729    xmlEntityPtr ent = NULL;
7730
7731    if ((str == NULL) || (*str == NULL))
7732        return(NULL);
7733    ptr = *str;
7734    cur = *ptr;
7735    if (cur != '&')
7736	return(NULL);
7737
7738    ptr++;
7739    name = xmlParseStringName(ctxt, &ptr);
7740    if (name == NULL) {
7741	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7742		       "xmlParseStringEntityRef: no name\n");
7743	*str = ptr;
7744	return(NULL);
7745    }
7746    if (*ptr != ';') {
7747	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7748        xmlFree(name);
7749	*str = ptr;
7750	return(NULL);
7751    }
7752    ptr++;
7753
7754
7755    /*
7756     * Predefined entites override any extra definition
7757     */
7758    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7759        ent = xmlGetPredefinedEntity(name);
7760        if (ent != NULL) {
7761            xmlFree(name);
7762            *str = ptr;
7763            return(ent);
7764        }
7765    }
7766
7767    /*
7768     * Increate the number of entity references parsed
7769     */
7770    ctxt->nbentities++;
7771
7772    /*
7773     * Ask first SAX for entity resolution, otherwise try the
7774     * entities which may have stored in the parser context.
7775     */
7776    if (ctxt->sax != NULL) {
7777	if (ctxt->sax->getEntity != NULL)
7778	    ent = ctxt->sax->getEntity(ctxt->userData, name);
7779	if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7780	    ent = xmlGetPredefinedEntity(name);
7781	if ((ent == NULL) && (ctxt->userData==ctxt)) {
7782	    ent = xmlSAX2GetEntity(ctxt, name);
7783	}
7784    }
7785    if (ctxt->instate == XML_PARSER_EOF) {
7786	xmlFree(name);
7787	return(NULL);
7788    }
7789
7790    /*
7791     * [ WFC: Entity Declared ]
7792     * In a document without any DTD, a document with only an
7793     * internal DTD subset which contains no parameter entity
7794     * references, or a document with "standalone='yes'", the
7795     * Name given in the entity reference must match that in an
7796     * entity declaration, except that well-formed documents
7797     * need not declare any of the following entities: amp, lt,
7798     * gt, apos, quot.
7799     * The declaration of a parameter entity must precede any
7800     * reference to it.
7801     * Similarly, the declaration of a general entity must
7802     * precede any reference to it which appears in a default
7803     * value in an attribute-list declaration. Note that if
7804     * entities are declared in the external subset or in
7805     * external parameter entities, a non-validating processor
7806     * is not obligated to read and process their declarations;
7807     * for such documents, the rule that an entity must be
7808     * declared is a well-formedness constraint only if
7809     * standalone='yes'.
7810     */
7811    if (ent == NULL) {
7812	if ((ctxt->standalone == 1) ||
7813	    ((ctxt->hasExternalSubset == 0) &&
7814	     (ctxt->hasPErefs == 0))) {
7815	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7816		     "Entity '%s' not defined\n", name);
7817	} else {
7818	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7819			  "Entity '%s' not defined\n",
7820			  name);
7821	}
7822	/* TODO ? check regressions ctxt->valid = 0; */
7823    }
7824
7825    /*
7826     * [ WFC: Parsed Entity ]
7827     * An entity reference must not contain the name of an
7828     * unparsed entity
7829     */
7830    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7831	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7832		 "Entity reference to unparsed entity %s\n", name);
7833    }
7834
7835    /*
7836     * [ WFC: No External Entity References ]
7837     * Attribute values cannot contain direct or indirect
7838     * entity references to external entities.
7839     */
7840    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7841	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7842	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7843	 "Attribute references external entity '%s'\n", name);
7844    }
7845    /*
7846     * [ WFC: No < in Attribute Values ]
7847     * The replacement text of any entity referred to directly or
7848     * indirectly in an attribute value (other than "&lt;") must
7849     * not contain a <.
7850     */
7851    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7852	     (ent != NULL) && (ent->content != NULL) &&
7853	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7854	     (xmlStrchr(ent->content, '<'))) {
7855	xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7856     "'<' in entity '%s' is not allowed in attributes values\n",
7857			  name);
7858    }
7859
7860    /*
7861     * Internal check, no parameter entities here ...
7862     */
7863    else {
7864	switch (ent->etype) {
7865	    case XML_INTERNAL_PARAMETER_ENTITY:
7866	    case XML_EXTERNAL_PARAMETER_ENTITY:
7867		xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7868	     "Attempt to reference the parameter entity '%s'\n",
7869				  name);
7870	    break;
7871	    default:
7872	    break;
7873	}
7874    }
7875
7876    /*
7877     * [ WFC: No Recursion ]
7878     * A parsed entity must not contain a recursive reference
7879     * to itself, either directly or indirectly.
7880     * Done somewhere else
7881     */
7882
7883    xmlFree(name);
7884    *str = ptr;
7885    return(ent);
7886}
7887
7888/**
7889 * xmlParsePEReference:
7890 * @ctxt:  an XML parser context
7891 *
7892 * parse PEReference declarations
7893 * The entity content is handled directly by pushing it's content as
7894 * a new input stream.
7895 *
7896 * [69] PEReference ::= '%' Name ';'
7897 *
7898 * [ WFC: No Recursion ]
7899 * A parsed entity must not contain a recursive
7900 * reference to itself, either directly or indirectly.
7901 *
7902 * [ WFC: Entity Declared ]
7903 * In a document without any DTD, a document with only an internal DTD
7904 * subset which contains no parameter entity references, or a document
7905 * with "standalone='yes'", ...  ... The declaration of a parameter
7906 * entity must precede any reference to it...
7907 *
7908 * [ VC: Entity Declared ]
7909 * In a document with an external subset or external parameter entities
7910 * with "standalone='no'", ...  ... The declaration of a parameter entity
7911 * must precede any reference to it...
7912 *
7913 * [ WFC: In DTD ]
7914 * Parameter-entity references may only appear in the DTD.
7915 * NOTE: misleading but this is handled.
7916 */
7917void
7918xmlParsePEReference(xmlParserCtxtPtr ctxt)
7919{
7920    const xmlChar *name;
7921    xmlEntityPtr entity = NULL;
7922    xmlParserInputPtr input;
7923
7924    if (RAW != '%')
7925        return;
7926    NEXT;
7927    name = xmlParseName(ctxt);
7928    if (name == NULL) {
7929	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7930		       "xmlParsePEReference: no name\n");
7931	return;
7932    }
7933    if (RAW != ';') {
7934	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7935        return;
7936    }
7937
7938    NEXT;
7939
7940    /*
7941     * Increate the number of entity references parsed
7942     */
7943    ctxt->nbentities++;
7944
7945    /*
7946     * Request the entity from SAX
7947     */
7948    if ((ctxt->sax != NULL) &&
7949	(ctxt->sax->getParameterEntity != NULL))
7950	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
7951    if (ctxt->instate == XML_PARSER_EOF)
7952	return;
7953    if (entity == NULL) {
7954	/*
7955	 * [ WFC: Entity Declared ]
7956	 * In a document without any DTD, a document with only an
7957	 * internal DTD subset which contains no parameter entity
7958	 * references, or a document with "standalone='yes'", ...
7959	 * ... The declaration of a parameter entity must precede
7960	 * any reference to it...
7961	 */
7962	if ((ctxt->standalone == 1) ||
7963	    ((ctxt->hasExternalSubset == 0) &&
7964	     (ctxt->hasPErefs == 0))) {
7965	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7966			      "PEReference: %%%s; not found\n",
7967			      name);
7968	} else {
7969	    /*
7970	     * [ VC: Entity Declared ]
7971	     * In a document with an external subset or external
7972	     * parameter entities with "standalone='no'", ...
7973	     * ... The declaration of a parameter entity must
7974	     * precede any reference to it...
7975	     */
7976	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7977			  "PEReference: %%%s; not found\n",
7978			  name, NULL);
7979	    ctxt->valid = 0;
7980	}
7981    } else {
7982	/*
7983	 * Internal checking in case the entity quest barfed
7984	 */
7985	if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
7986	    (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
7987	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7988		  "Internal: %%%s; is not a parameter entity\n",
7989			  name, NULL);
7990	} else if (ctxt->input->free != deallocblankswrapper) {
7991	    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
7992	    if (xmlPushInput(ctxt, input) < 0)
7993		return;
7994	} else {
7995	    /*
7996	     * TODO !!!
7997	     * handle the extra spaces added before and after
7998	     * c.f. http://www.w3.org/TR/REC-xml#as-PE
7999	     */
8000	    input = xmlNewEntityInputStream(ctxt, entity);
8001	    if (xmlPushInput(ctxt, input) < 0)
8002		return;
8003	    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8004		(CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8005		(IS_BLANK_CH(NXT(5)))) {
8006		xmlParseTextDecl(ctxt);
8007		if (ctxt->errNo ==
8008		    XML_ERR_UNSUPPORTED_ENCODING) {
8009		    /*
8010		     * The XML REC instructs us to stop parsing
8011		     * right here
8012		     */
8013		    ctxt->instate = XML_PARSER_EOF;
8014		    return;
8015		}
8016	    }
8017	}
8018    }
8019    ctxt->hasPErefs = 1;
8020}
8021
8022/**
8023 * xmlLoadEntityContent:
8024 * @ctxt:  an XML parser context
8025 * @entity: an unloaded system entity
8026 *
8027 * Load the original content of the given system entity from the
8028 * ExternalID/SystemID given. This is to be used for Included in Literal
8029 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8030 *
8031 * Returns 0 in case of success and -1 in case of failure
8032 */
8033static int
8034xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8035    xmlParserInputPtr input;
8036    xmlBufferPtr buf;
8037    int l, c;
8038    int count = 0;
8039
8040    if ((ctxt == NULL) || (entity == NULL) ||
8041        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8042	 (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8043	(entity->content != NULL)) {
8044	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8045	            "xmlLoadEntityContent parameter error");
8046        return(-1);
8047    }
8048
8049    if (xmlParserDebugEntities)
8050	xmlGenericError(xmlGenericErrorContext,
8051		"Reading %s entity content input\n", entity->name);
8052
8053    buf = xmlBufferCreate();
8054    if (buf == NULL) {
8055	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8056	            "xmlLoadEntityContent parameter error");
8057        return(-1);
8058    }
8059
8060    input = xmlNewEntityInputStream(ctxt, entity);
8061    if (input == NULL) {
8062	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8063	            "xmlLoadEntityContent input error");
8064	xmlBufferFree(buf);
8065        return(-1);
8066    }
8067
8068    /*
8069     * Push the entity as the current input, read char by char
8070     * saving to the buffer until the end of the entity or an error
8071     */
8072    if (xmlPushInput(ctxt, input) < 0) {
8073        xmlBufferFree(buf);
8074	return(-1);
8075    }
8076
8077    GROW;
8078    c = CUR_CHAR(l);
8079    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
8080           (IS_CHAR(c))) {
8081        xmlBufferAdd(buf, ctxt->input->cur, l);
8082	if (count++ > XML_PARSER_CHUNK_SIZE) {
8083	    count = 0;
8084	    GROW;
8085            if (ctxt->instate == XML_PARSER_EOF) {
8086                xmlBufferFree(buf);
8087                return(-1);
8088            }
8089	}
8090	NEXTL(l);
8091	c = CUR_CHAR(l);
8092	if (c == 0) {
8093	    count = 0;
8094	    GROW;
8095            if (ctxt->instate == XML_PARSER_EOF) {
8096                xmlBufferFree(buf);
8097                return(-1);
8098            }
8099	    c = CUR_CHAR(l);
8100	}
8101    }
8102
8103    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
8104        xmlPopInput(ctxt);
8105    } else if (!IS_CHAR(c)) {
8106        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8107                          "xmlLoadEntityContent: invalid char value %d\n",
8108	                  c);
8109	xmlBufferFree(buf);
8110	return(-1);
8111    }
8112    entity->content = buf->content;
8113    buf->content = NULL;
8114    xmlBufferFree(buf);
8115
8116    return(0);
8117}
8118
8119/**
8120 * xmlParseStringPEReference:
8121 * @ctxt:  an XML parser context
8122 * @str:  a pointer to an index in the string
8123 *
8124 * parse PEReference declarations
8125 *
8126 * [69] PEReference ::= '%' Name ';'
8127 *
8128 * [ WFC: No Recursion ]
8129 * A parsed entity must not contain a recursive
8130 * reference to itself, either directly or indirectly.
8131 *
8132 * [ WFC: Entity Declared ]
8133 * In a document without any DTD, a document with only an internal DTD
8134 * subset which contains no parameter entity references, or a document
8135 * with "standalone='yes'", ...  ... The declaration of a parameter
8136 * entity must precede any reference to it...
8137 *
8138 * [ VC: Entity Declared ]
8139 * In a document with an external subset or external parameter entities
8140 * with "standalone='no'", ...  ... The declaration of a parameter entity
8141 * must precede any reference to it...
8142 *
8143 * [ WFC: In DTD ]
8144 * Parameter-entity references may only appear in the DTD.
8145 * NOTE: misleading but this is handled.
8146 *
8147 * Returns the string of the entity content.
8148 *         str is updated to the current value of the index
8149 */
8150static xmlEntityPtr
8151xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8152    const xmlChar *ptr;
8153    xmlChar cur;
8154    xmlChar *name;
8155    xmlEntityPtr entity = NULL;
8156
8157    if ((str == NULL) || (*str == NULL)) return(NULL);
8158    ptr = *str;
8159    cur = *ptr;
8160    if (cur != '%')
8161        return(NULL);
8162    ptr++;
8163    name = xmlParseStringName(ctxt, &ptr);
8164    if (name == NULL) {
8165	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8166		       "xmlParseStringPEReference: no name\n");
8167	*str = ptr;
8168	return(NULL);
8169    }
8170    cur = *ptr;
8171    if (cur != ';') {
8172	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8173	xmlFree(name);
8174	*str = ptr;
8175	return(NULL);
8176    }
8177    ptr++;
8178
8179    /*
8180     * Increate the number of entity references parsed
8181     */
8182    ctxt->nbentities++;
8183
8184    /*
8185     * Request the entity from SAX
8186     */
8187    if ((ctxt->sax != NULL) &&
8188	(ctxt->sax->getParameterEntity != NULL))
8189	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8190    if (ctxt->instate == XML_PARSER_EOF) {
8191	xmlFree(name);
8192	return(NULL);
8193    }
8194    if (entity == NULL) {
8195	/*
8196	 * [ WFC: Entity Declared ]
8197	 * In a document without any DTD, a document with only an
8198	 * internal DTD subset which contains no parameter entity
8199	 * references, or a document with "standalone='yes'", ...
8200	 * ... The declaration of a parameter entity must precede
8201	 * any reference to it...
8202	 */
8203	if ((ctxt->standalone == 1) ||
8204	    ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8205	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8206		 "PEReference: %%%s; not found\n", name);
8207	} else {
8208	    /*
8209	     * [ VC: Entity Declared ]
8210	     * In a document with an external subset or external
8211	     * parameter entities with "standalone='no'", ...
8212	     * ... The declaration of a parameter entity must
8213	     * precede any reference to it...
8214	     */
8215	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8216			  "PEReference: %%%s; not found\n",
8217			  name, NULL);
8218	    ctxt->valid = 0;
8219	}
8220    } else {
8221	/*
8222	 * Internal checking in case the entity quest barfed
8223	 */
8224	if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8225	    (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8226	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8227			  "%%%s; is not a parameter entity\n",
8228			  name, NULL);
8229	}
8230    }
8231    ctxt->hasPErefs = 1;
8232    xmlFree(name);
8233    *str = ptr;
8234    return(entity);
8235}
8236
8237/**
8238 * xmlParseDocTypeDecl:
8239 * @ctxt:  an XML parser context
8240 *
8241 * parse a DOCTYPE declaration
8242 *
8243 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8244 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8245 *
8246 * [ VC: Root Element Type ]
8247 * The Name in the document type declaration must match the element
8248 * type of the root element.
8249 */
8250
8251void
8252xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8253    const xmlChar *name = NULL;
8254    xmlChar *ExternalID = NULL;
8255    xmlChar *URI = NULL;
8256
8257    /*
8258     * We know that '<!DOCTYPE' has been detected.
8259     */
8260    SKIP(9);
8261
8262    SKIP_BLANKS;
8263
8264    /*
8265     * Parse the DOCTYPE name.
8266     */
8267    name = xmlParseName(ctxt);
8268    if (name == NULL) {
8269	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8270		       "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8271    }
8272    ctxt->intSubName = name;
8273
8274    SKIP_BLANKS;
8275
8276    /*
8277     * Check for SystemID and ExternalID
8278     */
8279    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8280
8281    if ((URI != NULL) || (ExternalID != NULL)) {
8282        ctxt->hasExternalSubset = 1;
8283    }
8284    ctxt->extSubURI = URI;
8285    ctxt->extSubSystem = ExternalID;
8286
8287    SKIP_BLANKS;
8288
8289    /*
8290     * Create and update the internal subset.
8291     */
8292    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8293	(!ctxt->disableSAX))
8294	ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8295    if (ctxt->instate == XML_PARSER_EOF)
8296	return;
8297
8298    /*
8299     * Is there any internal subset declarations ?
8300     * they are handled separately in xmlParseInternalSubset()
8301     */
8302    if (RAW == '[')
8303	return;
8304
8305    /*
8306     * We should be at the end of the DOCTYPE declaration.
8307     */
8308    if (RAW != '>') {
8309	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8310    }
8311    NEXT;
8312}
8313
8314/**
8315 * xmlParseInternalSubset:
8316 * @ctxt:  an XML parser context
8317 *
8318 * parse the internal subset declaration
8319 *
8320 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8321 */
8322
8323static void
8324xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8325    /*
8326     * Is there any DTD definition ?
8327     */
8328    if (RAW == '[') {
8329        ctxt->instate = XML_PARSER_DTD;
8330        NEXT;
8331	/*
8332	 * Parse the succession of Markup declarations and
8333	 * PEReferences.
8334	 * Subsequence (markupdecl | PEReference | S)*
8335	 */
8336	while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
8337	    const xmlChar *check = CUR_PTR;
8338	    unsigned int cons = ctxt->input->consumed;
8339
8340	    SKIP_BLANKS;
8341	    xmlParseMarkupDecl(ctxt);
8342	    xmlParsePEReference(ctxt);
8343
8344	    /*
8345	     * Pop-up of finished entities.
8346	     */
8347	    while ((RAW == 0) && (ctxt->inputNr > 1))
8348		xmlPopInput(ctxt);
8349
8350	    if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
8351		xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8352	     "xmlParseInternalSubset: error detected in Markup declaration\n");
8353		break;
8354	    }
8355	}
8356	if (RAW == ']') {
8357	    NEXT;
8358	    SKIP_BLANKS;
8359	}
8360    }
8361
8362    /*
8363     * We should be at the end of the DOCTYPE declaration.
8364     */
8365    if (RAW != '>') {
8366	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8367    }
8368    NEXT;
8369}
8370
8371#ifdef LIBXML_SAX1_ENABLED
8372/**
8373 * xmlParseAttribute:
8374 * @ctxt:  an XML parser context
8375 * @value:  a xmlChar ** used to store the value of the attribute
8376 *
8377 * parse an attribute
8378 *
8379 * [41] Attribute ::= Name Eq AttValue
8380 *
8381 * [ WFC: No External Entity References ]
8382 * Attribute values cannot contain direct or indirect entity references
8383 * to external entities.
8384 *
8385 * [ WFC: No < in Attribute Values ]
8386 * The replacement text of any entity referred to directly or indirectly in
8387 * an attribute value (other than "&lt;") must not contain a <.
8388 *
8389 * [ VC: Attribute Value Type ]
8390 * The attribute must have been declared; the value must be of the type
8391 * declared for it.
8392 *
8393 * [25] Eq ::= S? '=' S?
8394 *
8395 * With namespace:
8396 *
8397 * [NS 11] Attribute ::= QName Eq AttValue
8398 *
8399 * Also the case QName == xmlns:??? is handled independently as a namespace
8400 * definition.
8401 *
8402 * Returns the attribute name, and the value in *value.
8403 */
8404
8405const xmlChar *
8406xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8407    const xmlChar *name;
8408    xmlChar *val;
8409
8410    *value = NULL;
8411    GROW;
8412    name = xmlParseName(ctxt);
8413    if (name == NULL) {
8414	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8415	               "error parsing attribute name\n");
8416        return(NULL);
8417    }
8418
8419    /*
8420     * read the value
8421     */
8422    SKIP_BLANKS;
8423    if (RAW == '=') {
8424        NEXT;
8425	SKIP_BLANKS;
8426	val = xmlParseAttValue(ctxt);
8427	ctxt->instate = XML_PARSER_CONTENT;
8428    } else {
8429	xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8430	       "Specification mandate value for attribute %s\n", name);
8431	return(NULL);
8432    }
8433
8434    /*
8435     * Check that xml:lang conforms to the specification
8436     * No more registered as an error, just generate a warning now
8437     * since this was deprecated in XML second edition
8438     */
8439    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8440	if (!xmlCheckLanguageID(val)) {
8441	    xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8442		          "Malformed value for xml:lang : %s\n",
8443			  val, NULL);
8444	}
8445    }
8446
8447    /*
8448     * Check that xml:space conforms to the specification
8449     */
8450    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8451	if (xmlStrEqual(val, BAD_CAST "default"))
8452	    *(ctxt->space) = 0;
8453	else if (xmlStrEqual(val, BAD_CAST "preserve"))
8454	    *(ctxt->space) = 1;
8455	else {
8456		xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8457"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8458                                 val, NULL);
8459	}
8460    }
8461
8462    *value = val;
8463    return(name);
8464}
8465
8466/**
8467 * xmlParseStartTag:
8468 * @ctxt:  an XML parser context
8469 *
8470 * parse a start of tag either for rule element or
8471 * EmptyElement. In both case we don't parse the tag closing chars.
8472 *
8473 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8474 *
8475 * [ WFC: Unique Att Spec ]
8476 * No attribute name may appear more than once in the same start-tag or
8477 * empty-element tag.
8478 *
8479 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8480 *
8481 * [ WFC: Unique Att Spec ]
8482 * No attribute name may appear more than once in the same start-tag or
8483 * empty-element tag.
8484 *
8485 * With namespace:
8486 *
8487 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8488 *
8489 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8490 *
8491 * Returns the element name parsed
8492 */
8493
8494const xmlChar *
8495xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8496    const xmlChar *name;
8497    const xmlChar *attname;
8498    xmlChar *attvalue;
8499    const xmlChar **atts = ctxt->atts;
8500    int nbatts = 0;
8501    int maxatts = ctxt->maxatts;
8502    int i;
8503
8504    if (RAW != '<') return(NULL);
8505    NEXT1;
8506
8507    name = xmlParseName(ctxt);
8508    if (name == NULL) {
8509	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8510	     "xmlParseStartTag: invalid element name\n");
8511        return(NULL);
8512    }
8513
8514    /*
8515     * Now parse the attributes, it ends up with the ending
8516     *
8517     * (S Attribute)* S?
8518     */
8519    SKIP_BLANKS;
8520    GROW;
8521
8522    while (((RAW != '>') &&
8523	   ((RAW != '/') || (NXT(1) != '>')) &&
8524	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8525	const xmlChar *q = CUR_PTR;
8526	unsigned int cons = ctxt->input->consumed;
8527
8528	attname = xmlParseAttribute(ctxt, &attvalue);
8529        if ((attname != NULL) && (attvalue != NULL)) {
8530	    /*
8531	     * [ WFC: Unique Att Spec ]
8532	     * No attribute name may appear more than once in the same
8533	     * start-tag or empty-element tag.
8534	     */
8535	    for (i = 0; i < nbatts;i += 2) {
8536	        if (xmlStrEqual(atts[i], attname)) {
8537		    xmlErrAttributeDup(ctxt, NULL, attname);
8538		    xmlFree(attvalue);
8539		    goto failed;
8540		}
8541	    }
8542	    /*
8543	     * Add the pair to atts
8544	     */
8545	    if (atts == NULL) {
8546	        maxatts = 22; /* allow for 10 attrs by default */
8547	        atts = (const xmlChar **)
8548		       xmlMalloc(maxatts * sizeof(xmlChar *));
8549		if (atts == NULL) {
8550		    xmlErrMemory(ctxt, NULL);
8551		    if (attvalue != NULL)
8552			xmlFree(attvalue);
8553		    goto failed;
8554		}
8555		ctxt->atts = atts;
8556		ctxt->maxatts = maxatts;
8557	    } else if (nbatts + 4 > maxatts) {
8558	        const xmlChar **n;
8559
8560	        maxatts *= 2;
8561	        n = (const xmlChar **) xmlRealloc((void *) atts,
8562					     maxatts * sizeof(const xmlChar *));
8563		if (n == NULL) {
8564		    xmlErrMemory(ctxt, NULL);
8565		    if (attvalue != NULL)
8566			xmlFree(attvalue);
8567		    goto failed;
8568		}
8569		atts = n;
8570		ctxt->atts = atts;
8571		ctxt->maxatts = maxatts;
8572	    }
8573	    atts[nbatts++] = attname;
8574	    atts[nbatts++] = attvalue;
8575	    atts[nbatts] = NULL;
8576	    atts[nbatts + 1] = NULL;
8577	} else {
8578	    if (attvalue != NULL)
8579		xmlFree(attvalue);
8580	}
8581
8582failed:
8583
8584	GROW
8585	if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8586	    break;
8587	if (!IS_BLANK_CH(RAW)) {
8588	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8589			   "attributes construct error\n");
8590	}
8591	SKIP_BLANKS;
8592        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
8593            (attname == NULL) && (attvalue == NULL)) {
8594	    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8595			   "xmlParseStartTag: problem parsing attributes\n");
8596	    break;
8597	}
8598	SHRINK;
8599        GROW;
8600    }
8601
8602    /*
8603     * SAX: Start of Element !
8604     */
8605    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8606	(!ctxt->disableSAX)) {
8607	if (nbatts > 0)
8608	    ctxt->sax->startElement(ctxt->userData, name, atts);
8609	else
8610	    ctxt->sax->startElement(ctxt->userData, name, NULL);
8611    }
8612
8613    if (atts != NULL) {
8614        /* Free only the content strings */
8615        for (i = 1;i < nbatts;i+=2)
8616	    if (atts[i] != NULL)
8617	       xmlFree((xmlChar *) atts[i]);
8618    }
8619    return(name);
8620}
8621
8622/**
8623 * xmlParseEndTag1:
8624 * @ctxt:  an XML parser context
8625 * @line:  line of the start tag
8626 * @nsNr:  number of namespaces on the start tag
8627 *
8628 * parse an end of tag
8629 *
8630 * [42] ETag ::= '</' Name S? '>'
8631 *
8632 * With namespace
8633 *
8634 * [NS 9] ETag ::= '</' QName S? '>'
8635 */
8636
8637static void
8638xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8639    const xmlChar *name;
8640
8641    GROW;
8642    if ((RAW != '<') || (NXT(1) != '/')) {
8643	xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8644		       "xmlParseEndTag: '</' not found\n");
8645	return;
8646    }
8647    SKIP(2);
8648
8649    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8650
8651    /*
8652     * We should definitely be at the ending "S? '>'" part
8653     */
8654    GROW;
8655    SKIP_BLANKS;
8656    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8657	xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8658    } else
8659	NEXT1;
8660
8661    /*
8662     * [ WFC: Element Type Match ]
8663     * The Name in an element's end-tag must match the element type in the
8664     * start-tag.
8665     *
8666     */
8667    if (name != (xmlChar*)1) {
8668        if (name == NULL) name = BAD_CAST "unparseable";
8669        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8670		     "Opening and ending tag mismatch: %s line %d and %s\n",
8671		                ctxt->name, line, name);
8672    }
8673
8674    /*
8675     * SAX: End of Tag
8676     */
8677    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8678	(!ctxt->disableSAX))
8679        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8680
8681    namePop(ctxt);
8682    spacePop(ctxt);
8683    return;
8684}
8685
8686/**
8687 * xmlParseEndTag:
8688 * @ctxt:  an XML parser context
8689 *
8690 * parse an end of tag
8691 *
8692 * [42] ETag ::= '</' Name S? '>'
8693 *
8694 * With namespace
8695 *
8696 * [NS 9] ETag ::= '</' QName S? '>'
8697 */
8698
8699void
8700xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8701    xmlParseEndTag1(ctxt, 0);
8702}
8703#endif /* LIBXML_SAX1_ENABLED */
8704
8705/************************************************************************
8706 *									*
8707 *		      SAX 2 specific operations				*
8708 *									*
8709 ************************************************************************/
8710
8711/*
8712 * xmlGetNamespace:
8713 * @ctxt:  an XML parser context
8714 * @prefix:  the prefix to lookup
8715 *
8716 * Lookup the namespace name for the @prefix (which ca be NULL)
8717 * The prefix must come from the @ctxt->dict dictionnary
8718 *
8719 * Returns the namespace name or NULL if not bound
8720 */
8721static const xmlChar *
8722xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8723    int i;
8724
8725    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8726    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8727        if (ctxt->nsTab[i] == prefix) {
8728	    if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8729	        return(NULL);
8730	    return(ctxt->nsTab[i + 1]);
8731	}
8732    return(NULL);
8733}
8734
8735/**
8736 * xmlParseQName:
8737 * @ctxt:  an XML parser context
8738 * @prefix:  pointer to store the prefix part
8739 *
8740 * parse an XML Namespace QName
8741 *
8742 * [6]  QName  ::= (Prefix ':')? LocalPart
8743 * [7]  Prefix  ::= NCName
8744 * [8]  LocalPart  ::= NCName
8745 *
8746 * Returns the Name parsed or NULL
8747 */
8748
8749static const xmlChar *
8750xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8751    const xmlChar *l, *p;
8752
8753    GROW;
8754
8755    l = xmlParseNCName(ctxt);
8756    if (l == NULL) {
8757        if (CUR == ':') {
8758	    l = xmlParseName(ctxt);
8759	    if (l != NULL) {
8760	        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8761		         "Failed to parse QName '%s'\n", l, NULL, NULL);
8762		*prefix = NULL;
8763		return(l);
8764	    }
8765	}
8766        return(NULL);
8767    }
8768    if (CUR == ':') {
8769        NEXT;
8770	p = l;
8771	l = xmlParseNCName(ctxt);
8772	if (l == NULL) {
8773	    xmlChar *tmp;
8774
8775            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8776	             "Failed to parse QName '%s:'\n", p, NULL, NULL);
8777	    l = xmlParseNmtoken(ctxt);
8778	    if (l == NULL)
8779		tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8780	    else {
8781		tmp = xmlBuildQName(l, p, NULL, 0);
8782		xmlFree((char *)l);
8783	    }
8784	    p = xmlDictLookup(ctxt->dict, tmp, -1);
8785	    if (tmp != NULL) xmlFree(tmp);
8786	    *prefix = NULL;
8787	    return(p);
8788	}
8789	if (CUR == ':') {
8790	    xmlChar *tmp;
8791
8792            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8793	             "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8794	    NEXT;
8795	    tmp = (xmlChar *) xmlParseName(ctxt);
8796	    if (tmp != NULL) {
8797	        tmp = xmlBuildQName(tmp, l, NULL, 0);
8798		l = xmlDictLookup(ctxt->dict, tmp, -1);
8799		if (tmp != NULL) xmlFree(tmp);
8800		*prefix = p;
8801		return(l);
8802	    }
8803	    tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8804	    l = xmlDictLookup(ctxt->dict, tmp, -1);
8805	    if (tmp != NULL) xmlFree(tmp);
8806	    *prefix = p;
8807	    return(l);
8808	}
8809	*prefix = p;
8810    } else
8811        *prefix = NULL;
8812    return(l);
8813}
8814
8815/**
8816 * xmlParseQNameAndCompare:
8817 * @ctxt:  an XML parser context
8818 * @name:  the localname
8819 * @prefix:  the prefix, if any.
8820 *
8821 * parse an XML name and compares for match
8822 * (specialized for endtag parsing)
8823 *
8824 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8825 * and the name for mismatch
8826 */
8827
8828static const xmlChar *
8829xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8830                        xmlChar const *prefix) {
8831    const xmlChar *cmp;
8832    const xmlChar *in;
8833    const xmlChar *ret;
8834    const xmlChar *prefix2;
8835
8836    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8837
8838    GROW;
8839    in = ctxt->input->cur;
8840
8841    cmp = prefix;
8842    while (*in != 0 && *in == *cmp) {
8843	++in;
8844	++cmp;
8845    }
8846    if ((*cmp == 0) && (*in == ':')) {
8847        in++;
8848	cmp = name;
8849	while (*in != 0 && *in == *cmp) {
8850	    ++in;
8851	    ++cmp;
8852	}
8853	if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8854	    /* success */
8855	    ctxt->input->cur = in;
8856	    return((const xmlChar*) 1);
8857	}
8858    }
8859    /*
8860     * all strings coms from the dictionary, equality can be done directly
8861     */
8862    ret = xmlParseQName (ctxt, &prefix2);
8863    if ((ret == name) && (prefix == prefix2))
8864	return((const xmlChar*) 1);
8865    return ret;
8866}
8867
8868/**
8869 * xmlParseAttValueInternal:
8870 * @ctxt:  an XML parser context
8871 * @len:  attribute len result
8872 * @alloc:  whether the attribute was reallocated as a new string
8873 * @normalize:  if 1 then further non-CDATA normalization must be done
8874 *
8875 * parse a value for an attribute.
8876 * NOTE: if no normalization is needed, the routine will return pointers
8877 *       directly from the data buffer.
8878 *
8879 * 3.3.3 Attribute-Value Normalization:
8880 * Before the value of an attribute is passed to the application or
8881 * checked for validity, the XML processor must normalize it as follows:
8882 * - a character reference is processed by appending the referenced
8883 *   character to the attribute value
8884 * - an entity reference is processed by recursively processing the
8885 *   replacement text of the entity
8886 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
8887 *   appending #x20 to the normalized value, except that only a single
8888 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
8889 *   parsed entity or the literal entity value of an internal parsed entity
8890 * - other characters are processed by appending them to the normalized value
8891 * If the declared value is not CDATA, then the XML processor must further
8892 * process the normalized attribute value by discarding any leading and
8893 * trailing space (#x20) characters, and by replacing sequences of space
8894 * (#x20) characters by a single space (#x20) character.
8895 * All attributes for which no declaration has been read should be treated
8896 * by a non-validating parser as if declared CDATA.
8897 *
8898 * Returns the AttValue parsed or NULL. The value has to be freed by the
8899 *     caller if it was copied, this can be detected by val[*len] == 0.
8900 */
8901
8902static xmlChar *
8903xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
8904                         int normalize)
8905{
8906    xmlChar limit = 0;
8907    const xmlChar *in = NULL, *start, *end, *last;
8908    xmlChar *ret = NULL;
8909
8910    GROW;
8911    in = (xmlChar *) CUR_PTR;
8912    if (*in != '"' && *in != '\'') {
8913        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
8914        return (NULL);
8915    }
8916    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
8917
8918    /*
8919     * try to handle in this routine the most common case where no
8920     * allocation of a new string is required and where content is
8921     * pure ASCII.
8922     */
8923    limit = *in++;
8924    end = ctxt->input->end;
8925    start = in;
8926    if (in >= end) {
8927        const xmlChar *oldbase = ctxt->input->base;
8928	GROW;
8929	if (oldbase != ctxt->input->base) {
8930	    long delta = ctxt->input->base - oldbase;
8931	    start = start + delta;
8932	    in = in + delta;
8933	}
8934	end = ctxt->input->end;
8935    }
8936    if (normalize) {
8937        /*
8938	 * Skip any leading spaces
8939	 */
8940	while ((in < end) && (*in != limit) &&
8941	       ((*in == 0x20) || (*in == 0x9) ||
8942	        (*in == 0xA) || (*in == 0xD))) {
8943	    in++;
8944	    start = in;
8945	    if (in >= end) {
8946		const xmlChar *oldbase = ctxt->input->base;
8947		GROW;
8948                if (ctxt->instate == XML_PARSER_EOF)
8949                    return(NULL);
8950		if (oldbase != ctxt->input->base) {
8951		    long delta = ctxt->input->base - oldbase;
8952		    start = start + delta;
8953		    in = in + delta;
8954		}
8955		end = ctxt->input->end;
8956                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
8957                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
8958                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
8959                                   "AttValue length too long\n");
8960                    return(NULL);
8961                }
8962	    }
8963	}
8964	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
8965	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
8966	    if ((*in++ == 0x20) && (*in == 0x20)) break;
8967	    if (in >= end) {
8968		const xmlChar *oldbase = ctxt->input->base;
8969		GROW;
8970                if (ctxt->instate == XML_PARSER_EOF)
8971                    return(NULL);
8972		if (oldbase != ctxt->input->base) {
8973		    long delta = ctxt->input->base - oldbase;
8974		    start = start + delta;
8975		    in = in + delta;
8976		}
8977		end = ctxt->input->end;
8978                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
8979                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
8980                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
8981                                   "AttValue length too long\n");
8982                    return(NULL);
8983                }
8984	    }
8985	}
8986	last = in;
8987	/*
8988	 * skip the trailing blanks
8989	 */
8990	while ((last[-1] == 0x20) && (last > start)) last--;
8991	while ((in < end) && (*in != limit) &&
8992	       ((*in == 0x20) || (*in == 0x9) ||
8993	        (*in == 0xA) || (*in == 0xD))) {
8994	    in++;
8995	    if (in >= end) {
8996		const xmlChar *oldbase = ctxt->input->base;
8997		GROW;
8998                if (ctxt->instate == XML_PARSER_EOF)
8999                    return(NULL);
9000		if (oldbase != ctxt->input->base) {
9001		    long delta = ctxt->input->base - oldbase;
9002		    start = start + delta;
9003		    in = in + delta;
9004		    last = last + delta;
9005		}
9006		end = ctxt->input->end;
9007                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9008                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9009                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9010                                   "AttValue length too long\n");
9011                    return(NULL);
9012                }
9013	    }
9014	}
9015        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9016            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9017            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9018                           "AttValue length too long\n");
9019            return(NULL);
9020        }
9021	if (*in != limit) goto need_complex;
9022    } else {
9023	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9024	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9025	    in++;
9026	    if (in >= end) {
9027		const xmlChar *oldbase = ctxt->input->base;
9028		GROW;
9029                if (ctxt->instate == XML_PARSER_EOF)
9030                    return(NULL);
9031		if (oldbase != ctxt->input->base) {
9032		    long delta = ctxt->input->base - oldbase;
9033		    start = start + delta;
9034		    in = in + delta;
9035		}
9036		end = ctxt->input->end;
9037                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9038                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9039                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9040                                   "AttValue length too long\n");
9041                    return(NULL);
9042                }
9043	    }
9044	}
9045	last = in;
9046        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9047            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9048            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9049                           "AttValue length too long\n");
9050            return(NULL);
9051        }
9052	if (*in != limit) goto need_complex;
9053    }
9054    in++;
9055    if (len != NULL) {
9056        *len = last - start;
9057        ret = (xmlChar *) start;
9058    } else {
9059        if (alloc) *alloc = 1;
9060        ret = xmlStrndup(start, last - start);
9061    }
9062    CUR_PTR = in;
9063    if (alloc) *alloc = 0;
9064    return ret;
9065need_complex:
9066    if (alloc) *alloc = 1;
9067    return xmlParseAttValueComplex(ctxt, len, normalize);
9068}
9069
9070/**
9071 * xmlParseAttribute2:
9072 * @ctxt:  an XML parser context
9073 * @pref:  the element prefix
9074 * @elem:  the element name
9075 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9076 * @value:  a xmlChar ** used to store the value of the attribute
9077 * @len:  an int * to save the length of the attribute
9078 * @alloc:  an int * to indicate if the attribute was allocated
9079 *
9080 * parse an attribute in the new SAX2 framework.
9081 *
9082 * Returns the attribute name, and the value in *value, .
9083 */
9084
9085static const xmlChar *
9086xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9087                   const xmlChar * pref, const xmlChar * elem,
9088                   const xmlChar ** prefix, xmlChar ** value,
9089                   int *len, int *alloc)
9090{
9091    const xmlChar *name;
9092    xmlChar *val, *internal_val = NULL;
9093    int normalize = 0;
9094
9095    *value = NULL;
9096    GROW;
9097    name = xmlParseQName(ctxt, prefix);
9098    if (name == NULL) {
9099        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9100                       "error parsing attribute name\n");
9101        return (NULL);
9102    }
9103
9104    /*
9105     * get the type if needed
9106     */
9107    if (ctxt->attsSpecial != NULL) {
9108        int type;
9109
9110        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
9111                                            pref, elem, *prefix, name);
9112        if (type != 0)
9113            normalize = 1;
9114    }
9115
9116    /*
9117     * read the value
9118     */
9119    SKIP_BLANKS;
9120    if (RAW == '=') {
9121        NEXT;
9122        SKIP_BLANKS;
9123        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9124	if (normalize) {
9125	    /*
9126	     * Sometimes a second normalisation pass for spaces is needed
9127	     * but that only happens if charrefs or entities refernces
9128	     * have been used in the attribute value, i.e. the attribute
9129	     * value have been extracted in an allocated string already.
9130	     */
9131	    if (*alloc) {
9132	        const xmlChar *val2;
9133
9134	        val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9135		if ((val2 != NULL) && (val2 != val)) {
9136		    xmlFree(val);
9137		    val = (xmlChar *) val2;
9138		}
9139	    }
9140	}
9141        ctxt->instate = XML_PARSER_CONTENT;
9142    } else {
9143        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9144                          "Specification mandate value for attribute %s\n",
9145                          name);
9146        return (NULL);
9147    }
9148
9149    if (*prefix == ctxt->str_xml) {
9150        /*
9151         * Check that xml:lang conforms to the specification
9152         * No more registered as an error, just generate a warning now
9153         * since this was deprecated in XML second edition
9154         */
9155        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9156            internal_val = xmlStrndup(val, *len);
9157            if (!xmlCheckLanguageID(internal_val)) {
9158                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9159                              "Malformed value for xml:lang : %s\n",
9160                              internal_val, NULL);
9161            }
9162        }
9163
9164        /*
9165         * Check that xml:space conforms to the specification
9166         */
9167        if (xmlStrEqual(name, BAD_CAST "space")) {
9168            internal_val = xmlStrndup(val, *len);
9169            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9170                *(ctxt->space) = 0;
9171            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9172                *(ctxt->space) = 1;
9173            else {
9174                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9175                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9176                              internal_val, NULL);
9177            }
9178        }
9179        if (internal_val) {
9180            xmlFree(internal_val);
9181        }
9182    }
9183
9184    *value = val;
9185    return (name);
9186}
9187/**
9188 * xmlParseStartTag2:
9189 * @ctxt:  an XML parser context
9190 *
9191 * parse a start of tag either for rule element or
9192 * EmptyElement. In both case we don't parse the tag closing chars.
9193 * This routine is called when running SAX2 parsing
9194 *
9195 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9196 *
9197 * [ WFC: Unique Att Spec ]
9198 * No attribute name may appear more than once in the same start-tag or
9199 * empty-element tag.
9200 *
9201 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9202 *
9203 * [ WFC: Unique Att Spec ]
9204 * No attribute name may appear more than once in the same start-tag or
9205 * empty-element tag.
9206 *
9207 * With namespace:
9208 *
9209 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9210 *
9211 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9212 *
9213 * Returns the element name parsed
9214 */
9215
9216static const xmlChar *
9217xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9218                  const xmlChar **URI, int *tlen) {
9219    const xmlChar *localname;
9220    const xmlChar *prefix;
9221    const xmlChar *attname;
9222    const xmlChar *aprefix;
9223    const xmlChar *nsname;
9224    xmlChar *attvalue;
9225    const xmlChar **atts = ctxt->atts;
9226    int maxatts = ctxt->maxatts;
9227    int nratts, nbatts, nbdef;
9228    int i, j, nbNs, attval, oldline, oldcol;
9229    const xmlChar *base;
9230    unsigned long cur;
9231    int nsNr = ctxt->nsNr;
9232
9233    if (RAW != '<') return(NULL);
9234    NEXT1;
9235
9236    /*
9237     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
9238     *       point since the attribute values may be stored as pointers to
9239     *       the buffer and calling SHRINK would destroy them !
9240     *       The Shrinking is only possible once the full set of attribute
9241     *       callbacks have been done.
9242     */
9243reparse:
9244    SHRINK;
9245    base = ctxt->input->base;
9246    cur = ctxt->input->cur - ctxt->input->base;
9247    oldline = ctxt->input->line;
9248    oldcol = ctxt->input->col;
9249    nbatts = 0;
9250    nratts = 0;
9251    nbdef = 0;
9252    nbNs = 0;
9253    attval = 0;
9254    /* Forget any namespaces added during an earlier parse of this element. */
9255    ctxt->nsNr = nsNr;
9256
9257    localname = xmlParseQName(ctxt, &prefix);
9258    if (localname == NULL) {
9259	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9260		       "StartTag: invalid element name\n");
9261        return(NULL);
9262    }
9263    *tlen = ctxt->input->cur - ctxt->input->base - cur;
9264
9265    /*
9266     * Now parse the attributes, it ends up with the ending
9267     *
9268     * (S Attribute)* S?
9269     */
9270    SKIP_BLANKS;
9271    GROW;
9272    if (ctxt->input->base != base) goto base_changed;
9273
9274    while (((RAW != '>') &&
9275	   ((RAW != '/') || (NXT(1) != '>')) &&
9276	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9277	const xmlChar *q = CUR_PTR;
9278	unsigned int cons = ctxt->input->consumed;
9279	int len = -1, alloc = 0;
9280
9281	attname = xmlParseAttribute2(ctxt, prefix, localname,
9282	                             &aprefix, &attvalue, &len, &alloc);
9283	if (ctxt->input->base != base) {
9284	    if ((attvalue != NULL) && (alloc != 0))
9285	        xmlFree(attvalue);
9286	    attvalue = NULL;
9287	    goto base_changed;
9288	}
9289        if ((attname != NULL) && (attvalue != NULL)) {
9290	    if (len < 0) len = xmlStrlen(attvalue);
9291            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9292	        const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9293		xmlURIPtr uri;
9294
9295                if (*URL != 0) {
9296		    uri = xmlParseURI((const char *) URL);
9297		    if (uri == NULL) {
9298			xmlNsErr(ctxt, XML_WAR_NS_URI,
9299			         "xmlns: '%s' is not a valid URI\n",
9300					   URL, NULL, NULL);
9301		    } else {
9302			if (uri->scheme == NULL) {
9303			    xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9304				      "xmlns: URI %s is not absolute\n",
9305				      URL, NULL, NULL);
9306			}
9307			xmlFreeURI(uri);
9308		    }
9309		    if (URL == ctxt->str_xml_ns) {
9310			if (attname != ctxt->str_xml) {
9311			    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9312			 "xml namespace URI cannot be the default namespace\n",
9313				     NULL, NULL, NULL);
9314			}
9315			goto skip_default_ns;
9316		    }
9317		    if ((len == 29) &&
9318			(xmlStrEqual(URL,
9319				 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9320			xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9321			     "reuse of the xmlns namespace name is forbidden\n",
9322				 NULL, NULL, NULL);
9323			goto skip_default_ns;
9324		    }
9325		}
9326		/*
9327		 * check that it's not a defined namespace
9328		 */
9329		for (j = 1;j <= nbNs;j++)
9330		    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9331			break;
9332		if (j <= nbNs)
9333		    xmlErrAttributeDup(ctxt, NULL, attname);
9334		else
9335		    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
9336skip_default_ns:
9337		if (alloc != 0) xmlFree(attvalue);
9338		SKIP_BLANKS;
9339		continue;
9340	    }
9341            if (aprefix == ctxt->str_xmlns) {
9342	        const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9343		xmlURIPtr uri;
9344
9345                if (attname == ctxt->str_xml) {
9346		    if (URL != ctxt->str_xml_ns) {
9347		        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9348			         "xml namespace prefix mapped to wrong URI\n",
9349			         NULL, NULL, NULL);
9350		    }
9351		    /*
9352		     * Do not keep a namespace definition node
9353		     */
9354		    goto skip_ns;
9355		}
9356                if (URL == ctxt->str_xml_ns) {
9357		    if (attname != ctxt->str_xml) {
9358		        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9359			         "xml namespace URI mapped to wrong prefix\n",
9360			         NULL, NULL, NULL);
9361		    }
9362		    goto skip_ns;
9363		}
9364                if (attname == ctxt->str_xmlns) {
9365		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9366			     "redefinition of the xmlns prefix is forbidden\n",
9367			     NULL, NULL, NULL);
9368		    goto skip_ns;
9369		}
9370		if ((len == 29) &&
9371		    (xmlStrEqual(URL,
9372		                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9373		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9374			     "reuse of the xmlns namespace name is forbidden\n",
9375			     NULL, NULL, NULL);
9376		    goto skip_ns;
9377		}
9378		if ((URL == NULL) || (URL[0] == 0)) {
9379		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9380		             "xmlns:%s: Empty XML namespace is not allowed\n",
9381			          attname, NULL, NULL);
9382		    goto skip_ns;
9383		} else {
9384		    uri = xmlParseURI((const char *) URL);
9385		    if (uri == NULL) {
9386			xmlNsErr(ctxt, XML_WAR_NS_URI,
9387			     "xmlns:%s: '%s' is not a valid URI\n",
9388					   attname, URL, NULL);
9389		    } else {
9390			if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9391			    xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9392				      "xmlns:%s: URI %s is not absolute\n",
9393				      attname, URL, NULL);
9394			}
9395			xmlFreeURI(uri);
9396		    }
9397		}
9398
9399		/*
9400		 * check that it's not a defined namespace
9401		 */
9402		for (j = 1;j <= nbNs;j++)
9403		    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9404			break;
9405		if (j <= nbNs)
9406		    xmlErrAttributeDup(ctxt, aprefix, attname);
9407		else
9408		    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9409skip_ns:
9410		if (alloc != 0) xmlFree(attvalue);
9411		SKIP_BLANKS;
9412		if (ctxt->input->base != base) goto base_changed;
9413		continue;
9414	    }
9415
9416	    /*
9417	     * Add the pair to atts
9418	     */
9419	    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9420	        if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9421		    if (attvalue[len] == 0)
9422			xmlFree(attvalue);
9423		    goto failed;
9424		}
9425	        maxatts = ctxt->maxatts;
9426		atts = ctxt->atts;
9427	    }
9428	    ctxt->attallocs[nratts++] = alloc;
9429	    atts[nbatts++] = attname;
9430	    atts[nbatts++] = aprefix;
9431	    atts[nbatts++] = NULL; /* the URI will be fetched later */
9432	    atts[nbatts++] = attvalue;
9433	    attvalue += len;
9434	    atts[nbatts++] = attvalue;
9435	    /*
9436	     * tag if some deallocation is needed
9437	     */
9438	    if (alloc != 0) attval = 1;
9439	} else {
9440	    if ((attvalue != NULL) && (attvalue[len] == 0))
9441		xmlFree(attvalue);
9442	}
9443
9444failed:
9445
9446	GROW
9447        if (ctxt->instate == XML_PARSER_EOF)
9448            break;
9449	if (ctxt->input->base != base) goto base_changed;
9450	if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9451	    break;
9452	if (!IS_BLANK_CH(RAW)) {
9453	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9454			   "attributes construct error\n");
9455	    break;
9456	}
9457	SKIP_BLANKS;
9458        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
9459            (attname == NULL) && (attvalue == NULL)) {
9460	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9461	         "xmlParseStartTag: problem parsing attributes\n");
9462	    break;
9463	}
9464        GROW;
9465	if (ctxt->input->base != base) goto base_changed;
9466    }
9467
9468    /*
9469     * The attributes defaulting
9470     */
9471    if (ctxt->attsDefault != NULL) {
9472        xmlDefAttrsPtr defaults;
9473
9474	defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9475	if (defaults != NULL) {
9476	    for (i = 0;i < defaults->nbAttrs;i++) {
9477	        attname = defaults->values[5 * i];
9478		aprefix = defaults->values[5 * i + 1];
9479
9480                /*
9481		 * special work for namespaces defaulted defs
9482		 */
9483		if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9484		    /*
9485		     * check that it's not a defined namespace
9486		     */
9487		    for (j = 1;j <= nbNs;j++)
9488		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9489			    break;
9490	            if (j <= nbNs) continue;
9491
9492		    nsname = xmlGetNamespace(ctxt, NULL);
9493		    if (nsname != defaults->values[5 * i + 2]) {
9494			if (nsPush(ctxt, NULL,
9495			           defaults->values[5 * i + 2]) > 0)
9496			    nbNs++;
9497		    }
9498		} else if (aprefix == ctxt->str_xmlns) {
9499		    /*
9500		     * check that it's not a defined namespace
9501		     */
9502		    for (j = 1;j <= nbNs;j++)
9503		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9504			    break;
9505	            if (j <= nbNs) continue;
9506
9507		    nsname = xmlGetNamespace(ctxt, attname);
9508		    if (nsname != defaults->values[2]) {
9509			if (nsPush(ctxt, attname,
9510			           defaults->values[5 * i + 2]) > 0)
9511			    nbNs++;
9512		    }
9513		} else {
9514		    /*
9515		     * check that it's not a defined attribute
9516		     */
9517		    for (j = 0;j < nbatts;j+=5) {
9518			if ((attname == atts[j]) && (aprefix == atts[j+1]))
9519			    break;
9520		    }
9521		    if (j < nbatts) continue;
9522
9523		    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9524			if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9525			    return(NULL);
9526			}
9527			maxatts = ctxt->maxatts;
9528			atts = ctxt->atts;
9529		    }
9530		    atts[nbatts++] = attname;
9531		    atts[nbatts++] = aprefix;
9532		    if (aprefix == NULL)
9533			atts[nbatts++] = NULL;
9534		    else
9535		        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9536		    atts[nbatts++] = defaults->values[5 * i + 2];
9537		    atts[nbatts++] = defaults->values[5 * i + 3];
9538		    if ((ctxt->standalone == 1) &&
9539		        (defaults->values[5 * i + 4] != NULL)) {
9540			xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9541	  "standalone: attribute %s on %s defaulted from external subset\n",
9542	                                 attname, localname);
9543		    }
9544		    nbdef++;
9545		}
9546	    }
9547	}
9548    }
9549
9550    /*
9551     * The attributes checkings
9552     */
9553    for (i = 0; i < nbatts;i += 5) {
9554        /*
9555	* The default namespace does not apply to attribute names.
9556	*/
9557	if (atts[i + 1] != NULL) {
9558	    nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9559	    if (nsname == NULL) {
9560		xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9561		    "Namespace prefix %s for %s on %s is not defined\n",
9562		    atts[i + 1], atts[i], localname);
9563	    }
9564	    atts[i + 2] = nsname;
9565	} else
9566	    nsname = NULL;
9567	/*
9568	 * [ WFC: Unique Att Spec ]
9569	 * No attribute name may appear more than once in the same
9570	 * start-tag or empty-element tag.
9571	 * As extended by the Namespace in XML REC.
9572	 */
9573        for (j = 0; j < i;j += 5) {
9574	    if (atts[i] == atts[j]) {
9575	        if (atts[i+1] == atts[j+1]) {
9576		    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9577		    break;
9578		}
9579		if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9580		    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9581			     "Namespaced Attribute %s in '%s' redefined\n",
9582			     atts[i], nsname, NULL);
9583		    break;
9584		}
9585	    }
9586	}
9587    }
9588
9589    nsname = xmlGetNamespace(ctxt, prefix);
9590    if ((prefix != NULL) && (nsname == NULL)) {
9591	xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9592	         "Namespace prefix %s on %s is not defined\n",
9593		 prefix, localname, NULL);
9594    }
9595    *pref = prefix;
9596    *URI = nsname;
9597
9598    /*
9599     * SAX: Start of Element !
9600     */
9601    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9602	(!ctxt->disableSAX)) {
9603	if (nbNs > 0)
9604	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9605			  nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9606			  nbatts / 5, nbdef, atts);
9607	else
9608	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9609	                  nsname, 0, NULL, nbatts / 5, nbdef, atts);
9610    }
9611
9612    /*
9613     * Free up attribute allocated strings if needed
9614     */
9615    if (attval != 0) {
9616	for (i = 3,j = 0; j < nratts;i += 5,j++)
9617	    if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9618	        xmlFree((xmlChar *) atts[i]);
9619    }
9620
9621    return(localname);
9622
9623base_changed:
9624    /*
9625     * the attribute strings are valid iif the base didn't changed
9626     */
9627    if (attval != 0) {
9628	for (i = 3,j = 0; j < nratts;i += 5,j++)
9629	    if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9630	        xmlFree((xmlChar *) atts[i]);
9631    }
9632    ctxt->input->cur = ctxt->input->base + cur;
9633    ctxt->input->line = oldline;
9634    ctxt->input->col = oldcol;
9635    if (ctxt->wellFormed == 1) {
9636	goto reparse;
9637    }
9638    return(NULL);
9639}
9640
9641/**
9642 * xmlParseEndTag2:
9643 * @ctxt:  an XML parser context
9644 * @line:  line of the start tag
9645 * @nsNr:  number of namespaces on the start tag
9646 *
9647 * parse an end of tag
9648 *
9649 * [42] ETag ::= '</' Name S? '>'
9650 *
9651 * With namespace
9652 *
9653 * [NS 9] ETag ::= '</' QName S? '>'
9654 */
9655
9656static void
9657xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
9658                const xmlChar *URI, int line, int nsNr, int tlen) {
9659    const xmlChar *name;
9660
9661    GROW;
9662    if ((RAW != '<') || (NXT(1) != '/')) {
9663	xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9664	return;
9665    }
9666    SKIP(2);
9667
9668    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
9669        if (ctxt->input->cur[tlen] == '>') {
9670	    ctxt->input->cur += tlen + 1;
9671	    goto done;
9672	}
9673	ctxt->input->cur += tlen;
9674	name = (xmlChar*)1;
9675    } else {
9676	if (prefix == NULL)
9677	    name = xmlParseNameAndCompare(ctxt, ctxt->name);
9678	else
9679	    name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
9680    }
9681
9682    /*
9683     * We should definitely be at the ending "S? '>'" part
9684     */
9685    GROW;
9686    if (ctxt->instate == XML_PARSER_EOF)
9687        return;
9688    SKIP_BLANKS;
9689    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9690	xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9691    } else
9692	NEXT1;
9693
9694    /*
9695     * [ WFC: Element Type Match ]
9696     * The Name in an element's end-tag must match the element type in the
9697     * start-tag.
9698     *
9699     */
9700    if (name != (xmlChar*)1) {
9701        if (name == NULL) name = BAD_CAST "unparseable";
9702        if ((line == 0) && (ctxt->node != NULL))
9703            line = ctxt->node->line;
9704        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9705		     "Opening and ending tag mismatch: %s line %d and %s\n",
9706		                ctxt->name, line, name);
9707    }
9708
9709    /*
9710     * SAX: End of Tag
9711     */
9712done:
9713    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9714	(!ctxt->disableSAX))
9715	ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
9716
9717    spacePop(ctxt);
9718    if (nsNr != 0)
9719	nsPop(ctxt, nsNr);
9720    return;
9721}
9722
9723/**
9724 * xmlParseCDSect:
9725 * @ctxt:  an XML parser context
9726 *
9727 * Parse escaped pure raw content.
9728 *
9729 * [18] CDSect ::= CDStart CData CDEnd
9730 *
9731 * [19] CDStart ::= '<![CDATA['
9732 *
9733 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9734 *
9735 * [21] CDEnd ::= ']]>'
9736 */
9737void
9738xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9739    xmlChar *buf = NULL;
9740    int len = 0;
9741    int size = XML_PARSER_BUFFER_SIZE;
9742    int r, rl;
9743    int	s, sl;
9744    int cur, l;
9745    int count = 0;
9746
9747    /* Check 2.6.0 was NXT(0) not RAW */
9748    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9749	SKIP(9);
9750    } else
9751        return;
9752
9753    ctxt->instate = XML_PARSER_CDATA_SECTION;
9754    r = CUR_CHAR(rl);
9755    if (!IS_CHAR(r)) {
9756	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9757	ctxt->instate = XML_PARSER_CONTENT;
9758        return;
9759    }
9760    NEXTL(rl);
9761    s = CUR_CHAR(sl);
9762    if (!IS_CHAR(s)) {
9763	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9764	ctxt->instate = XML_PARSER_CONTENT;
9765        return;
9766    }
9767    NEXTL(sl);
9768    cur = CUR_CHAR(l);
9769    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
9770    if (buf == NULL) {
9771	xmlErrMemory(ctxt, NULL);
9772	return;
9773    }
9774    while (IS_CHAR(cur) &&
9775           ((r != ']') || (s != ']') || (cur != '>'))) {
9776	if (len + 5 >= size) {
9777	    xmlChar *tmp;
9778
9779            if ((size > XML_MAX_TEXT_LENGTH) &&
9780                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9781                xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9782                             "CData section too big found", NULL);
9783                xmlFree (buf);
9784                return;
9785            }
9786	    tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
9787	    if (tmp == NULL) {
9788	        xmlFree(buf);
9789		xmlErrMemory(ctxt, NULL);
9790		return;
9791	    }
9792	    buf = tmp;
9793	    size *= 2;
9794	}
9795	COPY_BUF(rl,buf,len,r);
9796	r = s;
9797	rl = sl;
9798	s = cur;
9799	sl = l;
9800	count++;
9801	if (count > 50) {
9802	    GROW;
9803            if (ctxt->instate == XML_PARSER_EOF) {
9804		xmlFree(buf);
9805		return;
9806            }
9807	    count = 0;
9808	}
9809	NEXTL(l);
9810	cur = CUR_CHAR(l);
9811    }
9812    buf[len] = 0;
9813    ctxt->instate = XML_PARSER_CONTENT;
9814    if (cur != '>') {
9815	xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9816	                     "CData section not finished\n%.50s\n", buf);
9817	xmlFree(buf);
9818        return;
9819    }
9820    NEXTL(l);
9821
9822    /*
9823     * OK the buffer is to be consumed as cdata.
9824     */
9825    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9826	if (ctxt->sax->cdataBlock != NULL)
9827	    ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9828	else if (ctxt->sax->characters != NULL)
9829	    ctxt->sax->characters(ctxt->userData, buf, len);
9830    }
9831    xmlFree(buf);
9832}
9833
9834/**
9835 * xmlParseContent:
9836 * @ctxt:  an XML parser context
9837 *
9838 * Parse a content:
9839 *
9840 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
9841 */
9842
9843void
9844xmlParseContent(xmlParserCtxtPtr ctxt) {
9845    GROW;
9846    while ((RAW != 0) &&
9847	   ((RAW != '<') || (NXT(1) != '/')) &&
9848	   (ctxt->instate != XML_PARSER_EOF)) {
9849	const xmlChar *test = CUR_PTR;
9850	unsigned int cons = ctxt->input->consumed;
9851	const xmlChar *cur = ctxt->input->cur;
9852
9853	/*
9854	 * First case : a Processing Instruction.
9855	 */
9856	if ((*cur == '<') && (cur[1] == '?')) {
9857	    xmlParsePI(ctxt);
9858	}
9859
9860	/*
9861	 * Second case : a CDSection
9862	 */
9863	/* 2.6.0 test was *cur not RAW */
9864	else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9865	    xmlParseCDSect(ctxt);
9866	}
9867
9868	/*
9869	 * Third case :  a comment
9870	 */
9871	else if ((*cur == '<') && (NXT(1) == '!') &&
9872		 (NXT(2) == '-') && (NXT(3) == '-')) {
9873	    xmlParseComment(ctxt);
9874	    ctxt->instate = XML_PARSER_CONTENT;
9875	}
9876
9877	/*
9878	 * Fourth case :  a sub-element.
9879	 */
9880	else if (*cur == '<') {
9881	    xmlParseElement(ctxt);
9882	}
9883
9884	/*
9885	 * Fifth case : a reference. If if has not been resolved,
9886	 *    parsing returns it's Name, create the node
9887	 */
9888
9889	else if (*cur == '&') {
9890	    xmlParseReference(ctxt);
9891	}
9892
9893	/*
9894	 * Last case, text. Note that References are handled directly.
9895	 */
9896	else {
9897	    xmlParseCharData(ctxt, 0);
9898	}
9899
9900	GROW;
9901	/*
9902	 * Pop-up of finished entities.
9903	 */
9904	while ((RAW == 0) && (ctxt->inputNr > 1))
9905	    xmlPopInput(ctxt);
9906	SHRINK;
9907
9908	if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
9909	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9910	                "detected an error in element content\n");
9911	    ctxt->instate = XML_PARSER_EOF;
9912            break;
9913	}
9914    }
9915}
9916
9917/**
9918 * xmlParseElement:
9919 * @ctxt:  an XML parser context
9920 *
9921 * parse an XML element, this is highly recursive
9922 *
9923 * [39] element ::= EmptyElemTag | STag content ETag
9924 *
9925 * [ WFC: Element Type Match ]
9926 * The Name in an element's end-tag must match the element type in the
9927 * start-tag.
9928 *
9929 */
9930
9931void
9932xmlParseElement(xmlParserCtxtPtr ctxt) {
9933    const xmlChar *name;
9934    const xmlChar *prefix = NULL;
9935    const xmlChar *URI = NULL;
9936    xmlParserNodeInfo node_info;
9937    int line, tlen = 0;
9938    xmlNodePtr ret;
9939    int nsNr = ctxt->nsNr;
9940
9941    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
9942        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9943	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
9944		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
9945			  xmlParserMaxDepth);
9946	ctxt->instate = XML_PARSER_EOF;
9947	return;
9948    }
9949
9950    /* Capture start position */
9951    if (ctxt->record_info) {
9952        node_info.begin_pos = ctxt->input->consumed +
9953                          (CUR_PTR - ctxt->input->base);
9954	node_info.begin_line = ctxt->input->line;
9955    }
9956
9957    if (ctxt->spaceNr == 0)
9958	spacePush(ctxt, -1);
9959    else if (*ctxt->space == -2)
9960	spacePush(ctxt, -1);
9961    else
9962	spacePush(ctxt, *ctxt->space);
9963
9964    line = ctxt->input->line;
9965#ifdef LIBXML_SAX1_ENABLED
9966    if (ctxt->sax2)
9967#endif /* LIBXML_SAX1_ENABLED */
9968        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
9969#ifdef LIBXML_SAX1_ENABLED
9970    else
9971	name = xmlParseStartTag(ctxt);
9972#endif /* LIBXML_SAX1_ENABLED */
9973    if (ctxt->instate == XML_PARSER_EOF)
9974	return;
9975    if (name == NULL) {
9976	spacePop(ctxt);
9977        return;
9978    }
9979    namePush(ctxt, name);
9980    ret = ctxt->node;
9981
9982#ifdef LIBXML_VALID_ENABLED
9983    /*
9984     * [ VC: Root Element Type ]
9985     * The Name in the document type declaration must match the element
9986     * type of the root element.
9987     */
9988    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
9989        ctxt->node && (ctxt->node == ctxt->myDoc->children))
9990        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
9991#endif /* LIBXML_VALID_ENABLED */
9992
9993    /*
9994     * Check for an Empty Element.
9995     */
9996    if ((RAW == '/') && (NXT(1) == '>')) {
9997        SKIP(2);
9998	if (ctxt->sax2) {
9999	    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10000		(!ctxt->disableSAX))
10001		ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10002#ifdef LIBXML_SAX1_ENABLED
10003	} else {
10004	    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10005		(!ctxt->disableSAX))
10006		ctxt->sax->endElement(ctxt->userData, name);
10007#endif /* LIBXML_SAX1_ENABLED */
10008	}
10009	namePop(ctxt);
10010	spacePop(ctxt);
10011	if (nsNr != ctxt->nsNr)
10012	    nsPop(ctxt, ctxt->nsNr - nsNr);
10013	if ( ret != NULL && ctxt->record_info ) {
10014	   node_info.end_pos = ctxt->input->consumed +
10015			      (CUR_PTR - ctxt->input->base);
10016	   node_info.end_line = ctxt->input->line;
10017	   node_info.node = ret;
10018	   xmlParserAddNodeInfo(ctxt, &node_info);
10019	}
10020	return;
10021    }
10022    if (RAW == '>') {
10023        NEXT1;
10024    } else {
10025        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10026		     "Couldn't find end of Start Tag %s line %d\n",
10027		                name, line, NULL);
10028
10029	/*
10030	 * end of parsing of this node.
10031	 */
10032	nodePop(ctxt);
10033	namePop(ctxt);
10034	spacePop(ctxt);
10035	if (nsNr != ctxt->nsNr)
10036	    nsPop(ctxt, ctxt->nsNr - nsNr);
10037
10038	/*
10039	 * Capture end position and add node
10040	 */
10041	if ( ret != NULL && ctxt->record_info ) {
10042	   node_info.end_pos = ctxt->input->consumed +
10043			      (CUR_PTR - ctxt->input->base);
10044	   node_info.end_line = ctxt->input->line;
10045	   node_info.node = ret;
10046	   xmlParserAddNodeInfo(ctxt, &node_info);
10047	}
10048	return;
10049    }
10050
10051    /*
10052     * Parse the content of the element:
10053     */
10054    xmlParseContent(ctxt);
10055    if (ctxt->instate == XML_PARSER_EOF)
10056	return;
10057    if (!IS_BYTE_CHAR(RAW)) {
10058        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10059	 "Premature end of data in tag %s line %d\n",
10060		                name, line, NULL);
10061
10062	/*
10063	 * end of parsing of this node.
10064	 */
10065	nodePop(ctxt);
10066	namePop(ctxt);
10067	spacePop(ctxt);
10068	if (nsNr != ctxt->nsNr)
10069	    nsPop(ctxt, ctxt->nsNr - nsNr);
10070	return;
10071    }
10072
10073    /*
10074     * parse the end of tag: '</' should be here.
10075     */
10076    if (ctxt->sax2) {
10077	xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
10078	namePop(ctxt);
10079    }
10080#ifdef LIBXML_SAX1_ENABLED
10081      else
10082	xmlParseEndTag1(ctxt, line);
10083#endif /* LIBXML_SAX1_ENABLED */
10084
10085    /*
10086     * Capture end position and add node
10087     */
10088    if ( ret != NULL && ctxt->record_info ) {
10089       node_info.end_pos = ctxt->input->consumed +
10090                          (CUR_PTR - ctxt->input->base);
10091       node_info.end_line = ctxt->input->line;
10092       node_info.node = ret;
10093       xmlParserAddNodeInfo(ctxt, &node_info);
10094    }
10095}
10096
10097/**
10098 * xmlParseVersionNum:
10099 * @ctxt:  an XML parser context
10100 *
10101 * parse the XML version value.
10102 *
10103 * [26] VersionNum ::= '1.' [0-9]+
10104 *
10105 * In practice allow [0-9].[0-9]+ at that level
10106 *
10107 * Returns the string giving the XML version number, or NULL
10108 */
10109xmlChar *
10110xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10111    xmlChar *buf = NULL;
10112    int len = 0;
10113    int size = 10;
10114    xmlChar cur;
10115
10116    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
10117    if (buf == NULL) {
10118	xmlErrMemory(ctxt, NULL);
10119	return(NULL);
10120    }
10121    cur = CUR;
10122    if (!((cur >= '0') && (cur <= '9'))) {
10123	xmlFree(buf);
10124	return(NULL);
10125    }
10126    buf[len++] = cur;
10127    NEXT;
10128    cur=CUR;
10129    if (cur != '.') {
10130	xmlFree(buf);
10131	return(NULL);
10132    }
10133    buf[len++] = cur;
10134    NEXT;
10135    cur=CUR;
10136    while ((cur >= '0') && (cur <= '9')) {
10137	if (len + 1 >= size) {
10138	    xmlChar *tmp;
10139
10140	    size *= 2;
10141	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
10142	    if (tmp == NULL) {
10143	        xmlFree(buf);
10144		xmlErrMemory(ctxt, NULL);
10145		return(NULL);
10146	    }
10147	    buf = tmp;
10148	}
10149	buf[len++] = cur;
10150	NEXT;
10151	cur=CUR;
10152    }
10153    buf[len] = 0;
10154    return(buf);
10155}
10156
10157/**
10158 * xmlParseVersionInfo:
10159 * @ctxt:  an XML parser context
10160 *
10161 * parse the XML version.
10162 *
10163 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10164 *
10165 * [25] Eq ::= S? '=' S?
10166 *
10167 * Returns the version string, e.g. "1.0"
10168 */
10169
10170xmlChar *
10171xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10172    xmlChar *version = NULL;
10173
10174    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10175	SKIP(7);
10176	SKIP_BLANKS;
10177	if (RAW != '=') {
10178	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10179	    return(NULL);
10180        }
10181	NEXT;
10182	SKIP_BLANKS;
10183	if (RAW == '"') {
10184	    NEXT;
10185	    version = xmlParseVersionNum(ctxt);
10186	    if (RAW != '"') {
10187		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10188	    } else
10189	        NEXT;
10190	} else if (RAW == '\''){
10191	    NEXT;
10192	    version = xmlParseVersionNum(ctxt);
10193	    if (RAW != '\'') {
10194		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10195	    } else
10196	        NEXT;
10197	} else {
10198	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10199	}
10200    }
10201    return(version);
10202}
10203
10204/**
10205 * xmlParseEncName:
10206 * @ctxt:  an XML parser context
10207 *
10208 * parse the XML encoding name
10209 *
10210 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10211 *
10212 * Returns the encoding name value or NULL
10213 */
10214xmlChar *
10215xmlParseEncName(xmlParserCtxtPtr ctxt) {
10216    xmlChar *buf = NULL;
10217    int len = 0;
10218    int size = 10;
10219    xmlChar cur;
10220
10221    cur = CUR;
10222    if (((cur >= 'a') && (cur <= 'z')) ||
10223        ((cur >= 'A') && (cur <= 'Z'))) {
10224	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
10225	if (buf == NULL) {
10226	    xmlErrMemory(ctxt, NULL);
10227	    return(NULL);
10228	}
10229
10230	buf[len++] = cur;
10231	NEXT;
10232	cur = CUR;
10233	while (((cur >= 'a') && (cur <= 'z')) ||
10234	       ((cur >= 'A') && (cur <= 'Z')) ||
10235	       ((cur >= '0') && (cur <= '9')) ||
10236	       (cur == '.') || (cur == '_') ||
10237	       (cur == '-')) {
10238	    if (len + 1 >= size) {
10239	        xmlChar *tmp;
10240
10241		size *= 2;
10242		tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
10243		if (tmp == NULL) {
10244		    xmlErrMemory(ctxt, NULL);
10245		    xmlFree(buf);
10246		    return(NULL);
10247		}
10248		buf = tmp;
10249	    }
10250	    buf[len++] = cur;
10251	    NEXT;
10252	    cur = CUR;
10253	    if (cur == 0) {
10254	        SHRINK;
10255		GROW;
10256		cur = CUR;
10257	    }
10258        }
10259	buf[len] = 0;
10260    } else {
10261	xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10262    }
10263    return(buf);
10264}
10265
10266/**
10267 * xmlParseEncodingDecl:
10268 * @ctxt:  an XML parser context
10269 *
10270 * parse the XML encoding declaration
10271 *
10272 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10273 *
10274 * this setups the conversion filters.
10275 *
10276 * Returns the encoding value or NULL
10277 */
10278
10279const xmlChar *
10280xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10281    xmlChar *encoding = NULL;
10282
10283    SKIP_BLANKS;
10284    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
10285	SKIP(8);
10286	SKIP_BLANKS;
10287	if (RAW != '=') {
10288	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10289	    return(NULL);
10290        }
10291	NEXT;
10292	SKIP_BLANKS;
10293	if (RAW == '"') {
10294	    NEXT;
10295	    encoding = xmlParseEncName(ctxt);
10296	    if (RAW != '"') {
10297		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10298	    } else
10299	        NEXT;
10300	} else if (RAW == '\''){
10301	    NEXT;
10302	    encoding = xmlParseEncName(ctxt);
10303	    if (RAW != '\'') {
10304		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10305	    } else
10306	        NEXT;
10307	} else {
10308	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10309	}
10310
10311        /*
10312         * Non standard parsing, allowing the user to ignore encoding
10313         */
10314        if (ctxt->options & XML_PARSE_IGNORE_ENC)
10315            return(encoding);
10316
10317	/*
10318	 * UTF-16 encoding stwich has already taken place at this stage,
10319	 * more over the little-endian/big-endian selection is already done
10320	 */
10321        if ((encoding != NULL) &&
10322	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
10323	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
10324	    /*
10325	     * If no encoding was passed to the parser, that we are
10326	     * using UTF-16 and no decoder is present i.e. the
10327	     * document is apparently UTF-8 compatible, then raise an
10328	     * encoding mismatch fatal error
10329	     */
10330	    if ((ctxt->encoding == NULL) &&
10331	        (ctxt->input->buf != NULL) &&
10332	        (ctxt->input->buf->encoder == NULL)) {
10333		xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
10334		  "Document labelled UTF-16 but has UTF-8 content\n");
10335	    }
10336	    if (ctxt->encoding != NULL)
10337		xmlFree((xmlChar *) ctxt->encoding);
10338	    ctxt->encoding = encoding;
10339	}
10340	/*
10341	 * UTF-8 encoding is handled natively
10342	 */
10343        else if ((encoding != NULL) &&
10344	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
10345	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
10346	    if (ctxt->encoding != NULL)
10347		xmlFree((xmlChar *) ctxt->encoding);
10348	    ctxt->encoding = encoding;
10349	}
10350	else if (encoding != NULL) {
10351	    xmlCharEncodingHandlerPtr handler;
10352
10353	    if (ctxt->input->encoding != NULL)
10354		xmlFree((xmlChar *) ctxt->input->encoding);
10355	    ctxt->input->encoding = encoding;
10356
10357            handler = xmlFindCharEncodingHandler((const char *) encoding);
10358	    if (handler != NULL) {
10359		xmlSwitchToEncoding(ctxt, handler);
10360	    } else {
10361		xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
10362			"Unsupported encoding %s\n", encoding);
10363		return(NULL);
10364	    }
10365	}
10366    }
10367    return(encoding);
10368}
10369
10370/**
10371 * xmlParseSDDecl:
10372 * @ctxt:  an XML parser context
10373 *
10374 * parse the XML standalone declaration
10375 *
10376 * [32] SDDecl ::= S 'standalone' Eq
10377 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10378 *
10379 * [ VC: Standalone Document Declaration ]
10380 * TODO The standalone document declaration must have the value "no"
10381 * if any external markup declarations contain declarations of:
10382 *  - attributes with default values, if elements to which these
10383 *    attributes apply appear in the document without specifications
10384 *    of values for these attributes, or
10385 *  - entities (other than amp, lt, gt, apos, quot), if references
10386 *    to those entities appear in the document, or
10387 *  - attributes with values subject to normalization, where the
10388 *    attribute appears in the document with a value which will change
10389 *    as a result of normalization, or
10390 *  - element types with element content, if white space occurs directly
10391 *    within any instance of those types.
10392 *
10393 * Returns:
10394 *   1 if standalone="yes"
10395 *   0 if standalone="no"
10396 *  -2 if standalone attribute is missing or invalid
10397 *	  (A standalone value of -2 means that the XML declaration was found,
10398 *	   but no value was specified for the standalone attribute).
10399 */
10400
10401int
10402xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10403    int standalone = -2;
10404
10405    SKIP_BLANKS;
10406    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10407	SKIP(10);
10408        SKIP_BLANKS;
10409	if (RAW != '=') {
10410	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10411	    return(standalone);
10412        }
10413	NEXT;
10414	SKIP_BLANKS;
10415        if (RAW == '\''){
10416	    NEXT;
10417	    if ((RAW == 'n') && (NXT(1) == 'o')) {
10418	        standalone = 0;
10419                SKIP(2);
10420	    } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10421	               (NXT(2) == 's')) {
10422	        standalone = 1;
10423		SKIP(3);
10424            } else {
10425		xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10426	    }
10427	    if (RAW != '\'') {
10428		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10429	    } else
10430	        NEXT;
10431	} else if (RAW == '"'){
10432	    NEXT;
10433	    if ((RAW == 'n') && (NXT(1) == 'o')) {
10434	        standalone = 0;
10435		SKIP(2);
10436	    } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10437	               (NXT(2) == 's')) {
10438	        standalone = 1;
10439                SKIP(3);
10440            } else {
10441		xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10442	    }
10443	    if (RAW != '"') {
10444		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10445	    } else
10446	        NEXT;
10447	} else {
10448	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10449        }
10450    }
10451    return(standalone);
10452}
10453
10454/**
10455 * xmlParseXMLDecl:
10456 * @ctxt:  an XML parser context
10457 *
10458 * parse an XML declaration header
10459 *
10460 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10461 */
10462
10463void
10464xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10465    xmlChar *version;
10466
10467    /*
10468     * This value for standalone indicates that the document has an
10469     * XML declaration but it does not have a standalone attribute.
10470     * It will be overwritten later if a standalone attribute is found.
10471     */
10472    ctxt->input->standalone = -2;
10473
10474    /*
10475     * We know that '<?xml' is here.
10476     */
10477    SKIP(5);
10478
10479    if (!IS_BLANK_CH(RAW)) {
10480	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10481	               "Blank needed after '<?xml'\n");
10482    }
10483    SKIP_BLANKS;
10484
10485    /*
10486     * We must have the VersionInfo here.
10487     */
10488    version = xmlParseVersionInfo(ctxt);
10489    if (version == NULL) {
10490	xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10491    } else {
10492	if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10493	    /*
10494	     * Changed here for XML-1.0 5th edition
10495	     */
10496	    if (ctxt->options & XML_PARSE_OLD10) {
10497		xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10498			          "Unsupported version '%s'\n",
10499			          version);
10500	    } else {
10501	        if ((version[0] == '1') && ((version[1] == '.'))) {
10502		    xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10503		                  "Unsupported version '%s'\n",
10504				  version, NULL);
10505		} else {
10506		    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10507				      "Unsupported version '%s'\n",
10508				      version);
10509		}
10510	    }
10511	}
10512	if (ctxt->version != NULL)
10513	    xmlFree((void *) ctxt->version);
10514	ctxt->version = version;
10515    }
10516
10517    /*
10518     * We may have the encoding declaration
10519     */
10520    if (!IS_BLANK_CH(RAW)) {
10521        if ((RAW == '?') && (NXT(1) == '>')) {
10522	    SKIP(2);
10523	    return;
10524	}
10525	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10526    }
10527    xmlParseEncodingDecl(ctxt);
10528    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10529	/*
10530	 * The XML REC instructs us to stop parsing right here
10531	 */
10532        return;
10533    }
10534
10535    /*
10536     * We may have the standalone status.
10537     */
10538    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10539        if ((RAW == '?') && (NXT(1) == '>')) {
10540	    SKIP(2);
10541	    return;
10542	}
10543	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10544    }
10545
10546    /*
10547     * We can grow the input buffer freely at that point
10548     */
10549    GROW;
10550
10551    SKIP_BLANKS;
10552    ctxt->input->standalone = xmlParseSDDecl(ctxt);
10553
10554    SKIP_BLANKS;
10555    if ((RAW == '?') && (NXT(1) == '>')) {
10556        SKIP(2);
10557    } else if (RAW == '>') {
10558        /* Deprecated old WD ... */
10559	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10560	NEXT;
10561    } else {
10562	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10563	MOVETO_ENDTAG(CUR_PTR);
10564	NEXT;
10565    }
10566}
10567
10568/**
10569 * xmlParseMisc:
10570 * @ctxt:  an XML parser context
10571 *
10572 * parse an XML Misc* optional field.
10573 *
10574 * [27] Misc ::= Comment | PI |  S
10575 */
10576
10577void
10578xmlParseMisc(xmlParserCtxtPtr ctxt) {
10579    while ((ctxt->instate != XML_PARSER_EOF) &&
10580           (((RAW == '<') && (NXT(1) == '?')) ||
10581            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
10582            IS_BLANK_CH(CUR))) {
10583        if ((RAW == '<') && (NXT(1) == '?')) {
10584	    xmlParsePI(ctxt);
10585	} else if (IS_BLANK_CH(CUR)) {
10586	    NEXT;
10587	} else
10588	    xmlParseComment(ctxt);
10589    }
10590}
10591
10592/**
10593 * xmlParseDocument:
10594 * @ctxt:  an XML parser context
10595 *
10596 * parse an XML document (and build a tree if using the standard SAX
10597 * interface).
10598 *
10599 * [1] document ::= prolog element Misc*
10600 *
10601 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10602 *
10603 * Returns 0, -1 in case of error. the parser context is augmented
10604 *                as a result of the parsing.
10605 */
10606
10607int
10608xmlParseDocument(xmlParserCtxtPtr ctxt) {
10609    xmlChar start[4];
10610    xmlCharEncoding enc;
10611
10612    xmlInitParser();
10613
10614    if ((ctxt == NULL) || (ctxt->input == NULL))
10615        return(-1);
10616
10617    GROW;
10618
10619    /*
10620     * SAX: detecting the level.
10621     */
10622    xmlDetectSAX2(ctxt);
10623
10624    /*
10625     * SAX: beginning of the document processing.
10626     */
10627    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10628        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10629    if (ctxt->instate == XML_PARSER_EOF)
10630	return(-1);
10631
10632    if ((ctxt->encoding == NULL) &&
10633        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10634	/*
10635	 * Get the 4 first bytes and decode the charset
10636	 * if enc != XML_CHAR_ENCODING_NONE
10637	 * plug some encoding conversion routines.
10638	 */
10639	start[0] = RAW;
10640	start[1] = NXT(1);
10641	start[2] = NXT(2);
10642	start[3] = NXT(3);
10643	enc = xmlDetectCharEncoding(&start[0], 4);
10644	if (enc != XML_CHAR_ENCODING_NONE) {
10645	    xmlSwitchEncoding(ctxt, enc);
10646	}
10647    }
10648
10649
10650    if (CUR == 0) {
10651	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10652    }
10653
10654    /*
10655     * Check for the XMLDecl in the Prolog.
10656     * do not GROW here to avoid the detected encoder to decode more
10657     * than just the first line, unless the amount of data is really
10658     * too small to hold "<?xml version="1.0" encoding="foo"
10659     */
10660    if ((ctxt->input->end - ctxt->input->cur) < 35) {
10661       GROW;
10662    }
10663    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10664
10665	/*
10666	 * Note that we will switch encoding on the fly.
10667	 */
10668	xmlParseXMLDecl(ctxt);
10669	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10670	    /*
10671	     * The XML REC instructs us to stop parsing right here
10672	     */
10673	    return(-1);
10674	}
10675	ctxt->standalone = ctxt->input->standalone;
10676	SKIP_BLANKS;
10677    } else {
10678	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10679    }
10680    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10681        ctxt->sax->startDocument(ctxt->userData);
10682    if (ctxt->instate == XML_PARSER_EOF)
10683	return(-1);
10684
10685    /*
10686     * The Misc part of the Prolog
10687     */
10688    GROW;
10689    xmlParseMisc(ctxt);
10690
10691    /*
10692     * Then possibly doc type declaration(s) and more Misc
10693     * (doctypedecl Misc*)?
10694     */
10695    GROW;
10696    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10697
10698	ctxt->inSubset = 1;
10699	xmlParseDocTypeDecl(ctxt);
10700	if (RAW == '[') {
10701	    ctxt->instate = XML_PARSER_DTD;
10702	    xmlParseInternalSubset(ctxt);
10703	    if (ctxt->instate == XML_PARSER_EOF)
10704		return(-1);
10705	}
10706
10707	/*
10708	 * Create and update the external subset.
10709	 */
10710	ctxt->inSubset = 2;
10711	if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10712	    (!ctxt->disableSAX))
10713	    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10714	                              ctxt->extSubSystem, ctxt->extSubURI);
10715	if (ctxt->instate == XML_PARSER_EOF)
10716	    return(-1);
10717	ctxt->inSubset = 0;
10718
10719        xmlCleanSpecialAttr(ctxt);
10720
10721	ctxt->instate = XML_PARSER_PROLOG;
10722	xmlParseMisc(ctxt);
10723    }
10724
10725    /*
10726     * Time to start parsing the tree itself
10727     */
10728    GROW;
10729    if (RAW != '<') {
10730	xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10731		       "Start tag expected, '<' not found\n");
10732    } else {
10733	ctxt->instate = XML_PARSER_CONTENT;
10734	xmlParseElement(ctxt);
10735	ctxt->instate = XML_PARSER_EPILOG;
10736
10737
10738	/*
10739	 * The Misc part at the end
10740	 */
10741	xmlParseMisc(ctxt);
10742
10743	if (RAW != 0) {
10744	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10745	}
10746	ctxt->instate = XML_PARSER_EOF;
10747    }
10748
10749    /*
10750     * SAX: end of the document processing.
10751     */
10752    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10753        ctxt->sax->endDocument(ctxt->userData);
10754
10755    /*
10756     * Remove locally kept entity definitions if the tree was not built
10757     */
10758    if ((ctxt->myDoc != NULL) &&
10759	(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10760	xmlFreeDoc(ctxt->myDoc);
10761	ctxt->myDoc = NULL;
10762    }
10763
10764    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10765        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10766	if (ctxt->valid)
10767	    ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10768	if (ctxt->nsWellFormed)
10769	    ctxt->myDoc->properties |= XML_DOC_NSVALID;
10770	if (ctxt->options & XML_PARSE_OLD10)
10771	    ctxt->myDoc->properties |= XML_DOC_OLD10;
10772    }
10773    if (! ctxt->wellFormed) {
10774	ctxt->valid = 0;
10775	return(-1);
10776    }
10777    return(0);
10778}
10779
10780/**
10781 * xmlParseExtParsedEnt:
10782 * @ctxt:  an XML parser context
10783 *
10784 * parse a general parsed entity
10785 * An external general parsed entity is well-formed if it matches the
10786 * production labeled extParsedEnt.
10787 *
10788 * [78] extParsedEnt ::= TextDecl? content
10789 *
10790 * Returns 0, -1 in case of error. the parser context is augmented
10791 *                as a result of the parsing.
10792 */
10793
10794int
10795xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10796    xmlChar start[4];
10797    xmlCharEncoding enc;
10798
10799    if ((ctxt == NULL) || (ctxt->input == NULL))
10800        return(-1);
10801
10802    xmlDefaultSAXHandlerInit();
10803
10804    xmlDetectSAX2(ctxt);
10805
10806    GROW;
10807
10808    /*
10809     * SAX: beginning of the document processing.
10810     */
10811    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10812        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10813
10814    /*
10815     * Get the 4 first bytes and decode the charset
10816     * if enc != XML_CHAR_ENCODING_NONE
10817     * plug some encoding conversion routines.
10818     */
10819    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
10820	start[0] = RAW;
10821	start[1] = NXT(1);
10822	start[2] = NXT(2);
10823	start[3] = NXT(3);
10824	enc = xmlDetectCharEncoding(start, 4);
10825	if (enc != XML_CHAR_ENCODING_NONE) {
10826	    xmlSwitchEncoding(ctxt, enc);
10827	}
10828    }
10829
10830
10831    if (CUR == 0) {
10832	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10833    }
10834
10835    /*
10836     * Check for the XMLDecl in the Prolog.
10837     */
10838    GROW;
10839    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10840
10841	/*
10842	 * Note that we will switch encoding on the fly.
10843	 */
10844	xmlParseXMLDecl(ctxt);
10845	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10846	    /*
10847	     * The XML REC instructs us to stop parsing right here
10848	     */
10849	    return(-1);
10850	}
10851	SKIP_BLANKS;
10852    } else {
10853	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10854    }
10855    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10856        ctxt->sax->startDocument(ctxt->userData);
10857    if (ctxt->instate == XML_PARSER_EOF)
10858	return(-1);
10859
10860    /*
10861     * Doing validity checking on chunk doesn't make sense
10862     */
10863    ctxt->instate = XML_PARSER_CONTENT;
10864    ctxt->validate = 0;
10865    ctxt->loadsubset = 0;
10866    ctxt->depth = 0;
10867
10868    xmlParseContent(ctxt);
10869    if (ctxt->instate == XML_PARSER_EOF)
10870	return(-1);
10871
10872    if ((RAW == '<') && (NXT(1) == '/')) {
10873	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
10874    } else if (RAW != 0) {
10875	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
10876    }
10877
10878    /*
10879     * SAX: end of the document processing.
10880     */
10881    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10882        ctxt->sax->endDocument(ctxt->userData);
10883
10884    if (! ctxt->wellFormed) return(-1);
10885    return(0);
10886}
10887
10888#ifdef LIBXML_PUSH_ENABLED
10889/************************************************************************
10890 *									*
10891 *		Progressive parsing interfaces				*
10892 *									*
10893 ************************************************************************/
10894
10895/**
10896 * xmlParseLookupSequence:
10897 * @ctxt:  an XML parser context
10898 * @first:  the first char to lookup
10899 * @next:  the next char to lookup or zero
10900 * @third:  the next char to lookup or zero
10901 *
10902 * Try to find if a sequence (first, next, third) or  just (first next) or
10903 * (first) is available in the input stream.
10904 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
10905 * to avoid rescanning sequences of bytes, it DOES change the state of the
10906 * parser, do not use liberally.
10907 *
10908 * Returns the index to the current parsing point if the full sequence
10909 *      is available, -1 otherwise.
10910 */
10911static int
10912xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
10913                       xmlChar next, xmlChar third) {
10914    int base, len;
10915    xmlParserInputPtr in;
10916    const xmlChar *buf;
10917
10918    in = ctxt->input;
10919    if (in == NULL) return(-1);
10920    base = in->cur - in->base;
10921    if (base < 0) return(-1);
10922    if (ctxt->checkIndex > base)
10923        base = ctxt->checkIndex;
10924    if (in->buf == NULL) {
10925	buf = in->base;
10926	len = in->length;
10927    } else {
10928	buf = xmlBufContent(in->buf->buffer);
10929	len = xmlBufUse(in->buf->buffer);
10930    }
10931    /* take into account the sequence length */
10932    if (third) len -= 2;
10933    else if (next) len --;
10934    for (;base < len;base++) {
10935        if (buf[base] == first) {
10936	    if (third != 0) {
10937		if ((buf[base + 1] != next) ||
10938		    (buf[base + 2] != third)) continue;
10939	    } else if (next != 0) {
10940		if (buf[base + 1] != next) continue;
10941	    }
10942	    ctxt->checkIndex = 0;
10943#ifdef DEBUG_PUSH
10944	    if (next == 0)
10945		xmlGenericError(xmlGenericErrorContext,
10946			"PP: lookup '%c' found at %d\n",
10947			first, base);
10948	    else if (third == 0)
10949		xmlGenericError(xmlGenericErrorContext,
10950			"PP: lookup '%c%c' found at %d\n",
10951			first, next, base);
10952	    else
10953		xmlGenericError(xmlGenericErrorContext,
10954			"PP: lookup '%c%c%c' found at %d\n",
10955			first, next, third, base);
10956#endif
10957	    return(base - (in->cur - in->base));
10958	}
10959    }
10960    ctxt->checkIndex = base;
10961#ifdef DEBUG_PUSH
10962    if (next == 0)
10963	xmlGenericError(xmlGenericErrorContext,
10964		"PP: lookup '%c' failed\n", first);
10965    else if (third == 0)
10966	xmlGenericError(xmlGenericErrorContext,
10967		"PP: lookup '%c%c' failed\n", first, next);
10968    else
10969	xmlGenericError(xmlGenericErrorContext,
10970		"PP: lookup '%c%c%c' failed\n", first, next, third);
10971#endif
10972    return(-1);
10973}
10974
10975/**
10976 * xmlParseGetLasts:
10977 * @ctxt:  an XML parser context
10978 * @lastlt:  pointer to store the last '<' from the input
10979 * @lastgt:  pointer to store the last '>' from the input
10980 *
10981 * Lookup the last < and > in the current chunk
10982 */
10983static void
10984xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
10985                 const xmlChar **lastgt) {
10986    const xmlChar *tmp;
10987
10988    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
10989	xmlGenericError(xmlGenericErrorContext,
10990		    "Internal error: xmlParseGetLasts\n");
10991	return;
10992    }
10993    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
10994        tmp = ctxt->input->end;
10995	tmp--;
10996	while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
10997	if (tmp < ctxt->input->base) {
10998	    *lastlt = NULL;
10999	    *lastgt = NULL;
11000	} else {
11001	    *lastlt = tmp;
11002	    tmp++;
11003	    while ((tmp < ctxt->input->end) && (*tmp != '>')) {
11004	        if (*tmp == '\'') {
11005		    tmp++;
11006		    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
11007		    if (tmp < ctxt->input->end) tmp++;
11008		} else if (*tmp == '"') {
11009		    tmp++;
11010		    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
11011		    if (tmp < ctxt->input->end) tmp++;
11012		} else
11013		    tmp++;
11014	    }
11015	    if (tmp < ctxt->input->end)
11016	        *lastgt = tmp;
11017	    else {
11018	        tmp = *lastlt;
11019		tmp--;
11020		while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
11021		if (tmp >= ctxt->input->base)
11022		    *lastgt = tmp;
11023		else
11024		    *lastgt = NULL;
11025	    }
11026	}
11027    } else {
11028        *lastlt = NULL;
11029	*lastgt = NULL;
11030    }
11031}
11032/**
11033 * xmlCheckCdataPush:
11034 * @cur: pointer to the bock of characters
11035 * @len: length of the block in bytes
11036 *
11037 * Check that the block of characters is okay as SCdata content [20]
11038 *
11039 * Returns the number of bytes to pass if okay, a negative index where an
11040 *         UTF-8 error occured otherwise
11041 */
11042static int
11043xmlCheckCdataPush(const xmlChar *utf, int len) {
11044    int ix;
11045    unsigned char c;
11046    int codepoint;
11047
11048    if ((utf == NULL) || (len <= 0))
11049        return(0);
11050
11051    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11052        c = utf[ix];
11053        if ((c & 0x80) == 0x00) {	/* 1-byte code, starts with 10 */
11054	    if (c >= 0x20)
11055		ix++;
11056	    else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11057	        ix++;
11058	    else
11059	        return(-ix);
11060	} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11061	    if (ix + 2 > len) return(ix);
11062	    if ((utf[ix+1] & 0xc0 ) != 0x80)
11063	        return(-ix);
11064	    codepoint = (utf[ix] & 0x1f) << 6;
11065	    codepoint |= utf[ix+1] & 0x3f;
11066	    if (!xmlIsCharQ(codepoint))
11067	        return(-ix);
11068	    ix += 2;
11069	} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11070	    if (ix + 3 > len) return(ix);
11071	    if (((utf[ix+1] & 0xc0) != 0x80) ||
11072	        ((utf[ix+2] & 0xc0) != 0x80))
11073		    return(-ix);
11074	    codepoint = (utf[ix] & 0xf) << 12;
11075	    codepoint |= (utf[ix+1] & 0x3f) << 6;
11076	    codepoint |= utf[ix+2] & 0x3f;
11077	    if (!xmlIsCharQ(codepoint))
11078	        return(-ix);
11079	    ix += 3;
11080	} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11081	    if (ix + 4 > len) return(ix);
11082	    if (((utf[ix+1] & 0xc0) != 0x80) ||
11083	        ((utf[ix+2] & 0xc0) != 0x80) ||
11084		((utf[ix+3] & 0xc0) != 0x80))
11085		    return(-ix);
11086	    codepoint = (utf[ix] & 0x7) << 18;
11087	    codepoint |= (utf[ix+1] & 0x3f) << 12;
11088	    codepoint |= (utf[ix+2] & 0x3f) << 6;
11089	    codepoint |= utf[ix+3] & 0x3f;
11090	    if (!xmlIsCharQ(codepoint))
11091	        return(-ix);
11092	    ix += 4;
11093	} else				/* unknown encoding */
11094	    return(-ix);
11095      }
11096      return(ix);
11097}
11098
11099/**
11100 * xmlParseTryOrFinish:
11101 * @ctxt:  an XML parser context
11102 * @terminate:  last chunk indicator
11103 *
11104 * Try to progress on parsing
11105 *
11106 * Returns zero if no parsing was possible
11107 */
11108static int
11109xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11110    int ret = 0;
11111    int avail, tlen;
11112    xmlChar cur, next;
11113    const xmlChar *lastlt, *lastgt;
11114
11115    if (ctxt->input == NULL)
11116        return(0);
11117
11118#ifdef DEBUG_PUSH
11119    switch (ctxt->instate) {
11120	case XML_PARSER_EOF:
11121	    xmlGenericError(xmlGenericErrorContext,
11122		    "PP: try EOF\n"); break;
11123	case XML_PARSER_START:
11124	    xmlGenericError(xmlGenericErrorContext,
11125		    "PP: try START\n"); break;
11126	case XML_PARSER_MISC:
11127	    xmlGenericError(xmlGenericErrorContext,
11128		    "PP: try MISC\n");break;
11129	case XML_PARSER_COMMENT:
11130	    xmlGenericError(xmlGenericErrorContext,
11131		    "PP: try COMMENT\n");break;
11132	case XML_PARSER_PROLOG:
11133	    xmlGenericError(xmlGenericErrorContext,
11134		    "PP: try PROLOG\n");break;
11135	case XML_PARSER_START_TAG:
11136	    xmlGenericError(xmlGenericErrorContext,
11137		    "PP: try START_TAG\n");break;
11138	case XML_PARSER_CONTENT:
11139	    xmlGenericError(xmlGenericErrorContext,
11140		    "PP: try CONTENT\n");break;
11141	case XML_PARSER_CDATA_SECTION:
11142	    xmlGenericError(xmlGenericErrorContext,
11143		    "PP: try CDATA_SECTION\n");break;
11144	case XML_PARSER_END_TAG:
11145	    xmlGenericError(xmlGenericErrorContext,
11146		    "PP: try END_TAG\n");break;
11147	case XML_PARSER_ENTITY_DECL:
11148	    xmlGenericError(xmlGenericErrorContext,
11149		    "PP: try ENTITY_DECL\n");break;
11150	case XML_PARSER_ENTITY_VALUE:
11151	    xmlGenericError(xmlGenericErrorContext,
11152		    "PP: try ENTITY_VALUE\n");break;
11153	case XML_PARSER_ATTRIBUTE_VALUE:
11154	    xmlGenericError(xmlGenericErrorContext,
11155		    "PP: try ATTRIBUTE_VALUE\n");break;
11156	case XML_PARSER_DTD:
11157	    xmlGenericError(xmlGenericErrorContext,
11158		    "PP: try DTD\n");break;
11159	case XML_PARSER_EPILOG:
11160	    xmlGenericError(xmlGenericErrorContext,
11161		    "PP: try EPILOG\n");break;
11162	case XML_PARSER_PI:
11163	    xmlGenericError(xmlGenericErrorContext,
11164		    "PP: try PI\n");break;
11165        case XML_PARSER_IGNORE:
11166            xmlGenericError(xmlGenericErrorContext,
11167		    "PP: try IGNORE\n");break;
11168    }
11169#endif
11170
11171    if ((ctxt->input != NULL) &&
11172        (ctxt->input->cur - ctxt->input->base > 4096)) {
11173	xmlSHRINK(ctxt);
11174	ctxt->checkIndex = 0;
11175    }
11176    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11177
11178    while (ctxt->instate != XML_PARSER_EOF) {
11179	if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11180	    return(0);
11181
11182
11183	/*
11184	 * Pop-up of finished entities.
11185	 */
11186	while ((RAW == 0) && (ctxt->inputNr > 1))
11187	    xmlPopInput(ctxt);
11188
11189	if (ctxt->input == NULL) break;
11190	if (ctxt->input->buf == NULL)
11191	    avail = ctxt->input->length -
11192	            (ctxt->input->cur - ctxt->input->base);
11193	else {
11194	    /*
11195	     * If we are operating on converted input, try to flush
11196	     * remainng chars to avoid them stalling in the non-converted
11197	     * buffer. But do not do this in document start where
11198	     * encoding="..." may not have been read and we work on a
11199	     * guessed encoding.
11200	     */
11201	    if ((ctxt->instate != XML_PARSER_START) &&
11202	        (ctxt->input->buf->raw != NULL) &&
11203		(xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
11204                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
11205                                                 ctxt->input);
11206		size_t current = ctxt->input->cur - ctxt->input->base;
11207
11208		xmlParserInputBufferPush(ctxt->input->buf, 0, "");
11209                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
11210                                      base, current);
11211	    }
11212	    avail = xmlBufUse(ctxt->input->buf->buffer) -
11213		    (ctxt->input->cur - ctxt->input->base);
11214	}
11215        if (avail < 1)
11216	    goto done;
11217        switch (ctxt->instate) {
11218            case XML_PARSER_EOF:
11219	        /*
11220		 * Document parsing is done !
11221		 */
11222	        goto done;
11223            case XML_PARSER_START:
11224		if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
11225		    xmlChar start[4];
11226		    xmlCharEncoding enc;
11227
11228		    /*
11229		     * Very first chars read from the document flow.
11230		     */
11231		    if (avail < 4)
11232			goto done;
11233
11234		    /*
11235		     * Get the 4 first bytes and decode the charset
11236		     * if enc != XML_CHAR_ENCODING_NONE
11237		     * plug some encoding conversion routines,
11238		     * else xmlSwitchEncoding will set to (default)
11239		     * UTF8.
11240		     */
11241		    start[0] = RAW;
11242		    start[1] = NXT(1);
11243		    start[2] = NXT(2);
11244		    start[3] = NXT(3);
11245		    enc = xmlDetectCharEncoding(start, 4);
11246		    xmlSwitchEncoding(ctxt, enc);
11247		    break;
11248		}
11249
11250		if (avail < 2)
11251		    goto done;
11252		cur = ctxt->input->cur[0];
11253		next = ctxt->input->cur[1];
11254		if (cur == 0) {
11255		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11256			ctxt->sax->setDocumentLocator(ctxt->userData,
11257						      &xmlDefaultSAXLocator);
11258		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11259		    ctxt->instate = XML_PARSER_EOF;
11260#ifdef DEBUG_PUSH
11261		    xmlGenericError(xmlGenericErrorContext,
11262			    "PP: entering EOF\n");
11263#endif
11264		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11265			ctxt->sax->endDocument(ctxt->userData);
11266		    goto done;
11267		}
11268	        if ((cur == '<') && (next == '?')) {
11269		    /* PI or XML decl */
11270		    if (avail < 5) return(ret);
11271		    if ((!terminate) &&
11272		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11273			return(ret);
11274		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11275			ctxt->sax->setDocumentLocator(ctxt->userData,
11276						      &xmlDefaultSAXLocator);
11277		    if ((ctxt->input->cur[2] == 'x') &&
11278			(ctxt->input->cur[3] == 'm') &&
11279			(ctxt->input->cur[4] == 'l') &&
11280			(IS_BLANK_CH(ctxt->input->cur[5]))) {
11281			ret += 5;
11282#ifdef DEBUG_PUSH
11283			xmlGenericError(xmlGenericErrorContext,
11284				"PP: Parsing XML Decl\n");
11285#endif
11286			xmlParseXMLDecl(ctxt);
11287			if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11288			    /*
11289			     * The XML REC instructs us to stop parsing right
11290			     * here
11291			     */
11292			    ctxt->instate = XML_PARSER_EOF;
11293			    return(0);
11294			}
11295			ctxt->standalone = ctxt->input->standalone;
11296			if ((ctxt->encoding == NULL) &&
11297			    (ctxt->input->encoding != NULL))
11298			    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
11299			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11300			    (!ctxt->disableSAX))
11301			    ctxt->sax->startDocument(ctxt->userData);
11302			ctxt->instate = XML_PARSER_MISC;
11303#ifdef DEBUG_PUSH
11304			xmlGenericError(xmlGenericErrorContext,
11305				"PP: entering MISC\n");
11306#endif
11307		    } else {
11308			ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11309			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11310			    (!ctxt->disableSAX))
11311			    ctxt->sax->startDocument(ctxt->userData);
11312			ctxt->instate = XML_PARSER_MISC;
11313#ifdef DEBUG_PUSH
11314			xmlGenericError(xmlGenericErrorContext,
11315				"PP: entering MISC\n");
11316#endif
11317		    }
11318		} else {
11319		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11320			ctxt->sax->setDocumentLocator(ctxt->userData,
11321						      &xmlDefaultSAXLocator);
11322		    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11323		    if (ctxt->version == NULL) {
11324		        xmlErrMemory(ctxt, NULL);
11325			break;
11326		    }
11327		    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11328		        (!ctxt->disableSAX))
11329			ctxt->sax->startDocument(ctxt->userData);
11330		    ctxt->instate = XML_PARSER_MISC;
11331#ifdef DEBUG_PUSH
11332		    xmlGenericError(xmlGenericErrorContext,
11333			    "PP: entering MISC\n");
11334#endif
11335		}
11336		break;
11337            case XML_PARSER_START_TAG: {
11338	        const xmlChar *name;
11339		const xmlChar *prefix = NULL;
11340		const xmlChar *URI = NULL;
11341		int nsNr = ctxt->nsNr;
11342
11343		if ((avail < 2) && (ctxt->inputNr == 1))
11344		    goto done;
11345		cur = ctxt->input->cur[0];
11346	        if (cur != '<') {
11347		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11348		    ctxt->instate = XML_PARSER_EOF;
11349		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11350			ctxt->sax->endDocument(ctxt->userData);
11351		    goto done;
11352		}
11353		if (!terminate) {
11354		    if (ctxt->progressive) {
11355		        /* > can be found unescaped in attribute values */
11356		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11357			    goto done;
11358		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11359			goto done;
11360		    }
11361		}
11362		if (ctxt->spaceNr == 0)
11363		    spacePush(ctxt, -1);
11364		else if (*ctxt->space == -2)
11365		    spacePush(ctxt, -1);
11366		else
11367		    spacePush(ctxt, *ctxt->space);
11368#ifdef LIBXML_SAX1_ENABLED
11369		if (ctxt->sax2)
11370#endif /* LIBXML_SAX1_ENABLED */
11371		    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
11372#ifdef LIBXML_SAX1_ENABLED
11373		else
11374		    name = xmlParseStartTag(ctxt);
11375#endif /* LIBXML_SAX1_ENABLED */
11376		if (ctxt->instate == XML_PARSER_EOF)
11377		    goto done;
11378		if (name == NULL) {
11379		    spacePop(ctxt);
11380		    ctxt->instate = XML_PARSER_EOF;
11381		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11382			ctxt->sax->endDocument(ctxt->userData);
11383		    goto done;
11384		}
11385#ifdef LIBXML_VALID_ENABLED
11386		/*
11387		 * [ VC: Root Element Type ]
11388		 * The Name in the document type declaration must match
11389		 * the element type of the root element.
11390		 */
11391		if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11392		    ctxt->node && (ctxt->node == ctxt->myDoc->children))
11393		    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11394#endif /* LIBXML_VALID_ENABLED */
11395
11396		/*
11397		 * Check for an Empty Element.
11398		 */
11399		if ((RAW == '/') && (NXT(1) == '>')) {
11400		    SKIP(2);
11401
11402		    if (ctxt->sax2) {
11403			if ((ctxt->sax != NULL) &&
11404			    (ctxt->sax->endElementNs != NULL) &&
11405			    (!ctxt->disableSAX))
11406			    ctxt->sax->endElementNs(ctxt->userData, name,
11407			                            prefix, URI);
11408			if (ctxt->nsNr - nsNr > 0)
11409			    nsPop(ctxt, ctxt->nsNr - nsNr);
11410#ifdef LIBXML_SAX1_ENABLED
11411		    } else {
11412			if ((ctxt->sax != NULL) &&
11413			    (ctxt->sax->endElement != NULL) &&
11414			    (!ctxt->disableSAX))
11415			    ctxt->sax->endElement(ctxt->userData, name);
11416#endif /* LIBXML_SAX1_ENABLED */
11417		    }
11418		    if (ctxt->instate == XML_PARSER_EOF)
11419			goto done;
11420		    spacePop(ctxt);
11421		    if (ctxt->nameNr == 0) {
11422			ctxt->instate = XML_PARSER_EPILOG;
11423		    } else {
11424			ctxt->instate = XML_PARSER_CONTENT;
11425		    }
11426                    ctxt->progressive = 1;
11427		    break;
11428		}
11429		if (RAW == '>') {
11430		    NEXT;
11431		} else {
11432		    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11433					 "Couldn't find end of Start Tag %s\n",
11434					 name);
11435		    nodePop(ctxt);
11436		    spacePop(ctxt);
11437		}
11438		if (ctxt->sax2)
11439		    nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
11440#ifdef LIBXML_SAX1_ENABLED
11441		else
11442		    namePush(ctxt, name);
11443#endif /* LIBXML_SAX1_ENABLED */
11444
11445		ctxt->instate = XML_PARSER_CONTENT;
11446                ctxt->progressive = 1;
11447                break;
11448	    }
11449            case XML_PARSER_CONTENT: {
11450		const xmlChar *test;
11451		unsigned int cons;
11452		if ((avail < 2) && (ctxt->inputNr == 1))
11453		    goto done;
11454		cur = ctxt->input->cur[0];
11455		next = ctxt->input->cur[1];
11456
11457		test = CUR_PTR;
11458	        cons = ctxt->input->consumed;
11459		if ((cur == '<') && (next == '/')) {
11460		    ctxt->instate = XML_PARSER_END_TAG;
11461		    break;
11462	        } else if ((cur == '<') && (next == '?')) {
11463		    if ((!terminate) &&
11464		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11465                        ctxt->progressive = XML_PARSER_PI;
11466			goto done;
11467                    }
11468		    xmlParsePI(ctxt);
11469		    ctxt->instate = XML_PARSER_CONTENT;
11470                    ctxt->progressive = 1;
11471		} else if ((cur == '<') && (next != '!')) {
11472		    ctxt->instate = XML_PARSER_START_TAG;
11473		    break;
11474		} else if ((cur == '<') && (next == '!') &&
11475		           (ctxt->input->cur[2] == '-') &&
11476			   (ctxt->input->cur[3] == '-')) {
11477		    int term;
11478
11479	            if (avail < 4)
11480		        goto done;
11481		    ctxt->input->cur += 4;
11482		    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11483		    ctxt->input->cur -= 4;
11484		    if ((!terminate) && (term < 0)) {
11485                        ctxt->progressive = XML_PARSER_COMMENT;
11486			goto done;
11487                    }
11488		    xmlParseComment(ctxt);
11489		    ctxt->instate = XML_PARSER_CONTENT;
11490                    ctxt->progressive = 1;
11491		} else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11492		    (ctxt->input->cur[2] == '[') &&
11493		    (ctxt->input->cur[3] == 'C') &&
11494		    (ctxt->input->cur[4] == 'D') &&
11495		    (ctxt->input->cur[5] == 'A') &&
11496		    (ctxt->input->cur[6] == 'T') &&
11497		    (ctxt->input->cur[7] == 'A') &&
11498		    (ctxt->input->cur[8] == '[')) {
11499		    SKIP(9);
11500		    ctxt->instate = XML_PARSER_CDATA_SECTION;
11501		    break;
11502		} else if ((cur == '<') && (next == '!') &&
11503		           (avail < 9)) {
11504		    goto done;
11505		} else if (cur == '&') {
11506		    if ((!terminate) &&
11507		        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11508			goto done;
11509		    xmlParseReference(ctxt);
11510		} else {
11511		    /* TODO Avoid the extra copy, handle directly !!! */
11512		    /*
11513		     * Goal of the following test is:
11514		     *  - minimize calls to the SAX 'character' callback
11515		     *    when they are mergeable
11516		     *  - handle an problem for isBlank when we only parse
11517		     *    a sequence of blank chars and the next one is
11518		     *    not available to check against '<' presence.
11519		     *  - tries to homogenize the differences in SAX
11520		     *    callbacks between the push and pull versions
11521		     *    of the parser.
11522		     */
11523		    if ((ctxt->inputNr == 1) &&
11524		        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11525			if (!terminate) {
11526			    if (ctxt->progressive) {
11527				if ((lastlt == NULL) ||
11528				    (ctxt->input->cur > lastlt))
11529				    goto done;
11530			    } else if (xmlParseLookupSequence(ctxt,
11531			                                      '<', 0, 0) < 0) {
11532				goto done;
11533			    }
11534			}
11535                    }
11536		    ctxt->checkIndex = 0;
11537		    xmlParseCharData(ctxt, 0);
11538		}
11539		/*
11540		 * Pop-up of finished entities.
11541		 */
11542		while ((RAW == 0) && (ctxt->inputNr > 1))
11543		    xmlPopInput(ctxt);
11544		if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
11545		    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11546		                "detected an error in element content\n");
11547		    ctxt->instate = XML_PARSER_EOF;
11548		    break;
11549		}
11550		break;
11551	    }
11552            case XML_PARSER_END_TAG:
11553		if (avail < 2)
11554		    goto done;
11555		if (!terminate) {
11556		    if (ctxt->progressive) {
11557		        /* > can be found unescaped in attribute values */
11558		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11559			    goto done;
11560		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11561			goto done;
11562		    }
11563		}
11564		if (ctxt->sax2) {
11565		    xmlParseEndTag2(ctxt,
11566		           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
11567		           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
11568		       (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
11569		    nameNsPop(ctxt);
11570		}
11571#ifdef LIBXML_SAX1_ENABLED
11572		  else
11573		    xmlParseEndTag1(ctxt, 0);
11574#endif /* LIBXML_SAX1_ENABLED */
11575		if (ctxt->instate == XML_PARSER_EOF) {
11576		    /* Nothing */
11577		} else if (ctxt->nameNr == 0) {
11578		    ctxt->instate = XML_PARSER_EPILOG;
11579		} else {
11580		    ctxt->instate = XML_PARSER_CONTENT;
11581		}
11582		break;
11583            case XML_PARSER_CDATA_SECTION: {
11584	        /*
11585		 * The Push mode need to have the SAX callback for
11586		 * cdataBlock merge back contiguous callbacks.
11587		 */
11588		int base;
11589
11590		base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11591		if (base < 0) {
11592		    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11593		        int tmp;
11594
11595			tmp = xmlCheckCdataPush(ctxt->input->cur,
11596			                        XML_PARSER_BIG_BUFFER_SIZE);
11597			if (tmp < 0) {
11598			    tmp = -tmp;
11599			    ctxt->input->cur += tmp;
11600			    goto encoding_error;
11601			}
11602			if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11603			    if (ctxt->sax->cdataBlock != NULL)
11604				ctxt->sax->cdataBlock(ctxt->userData,
11605				                      ctxt->input->cur, tmp);
11606			    else if (ctxt->sax->characters != NULL)
11607				ctxt->sax->characters(ctxt->userData,
11608				                      ctxt->input->cur, tmp);
11609			}
11610			if (ctxt->instate == XML_PARSER_EOF)
11611			    goto done;
11612			SKIPL(tmp);
11613			ctxt->checkIndex = 0;
11614		    }
11615		    goto done;
11616		} else {
11617		    int tmp;
11618
11619		    tmp = xmlCheckCdataPush(ctxt->input->cur, base);
11620		    if ((tmp < 0) || (tmp != base)) {
11621			tmp = -tmp;
11622			ctxt->input->cur += tmp;
11623			goto encoding_error;
11624		    }
11625		    if ((ctxt->sax != NULL) && (base == 0) &&
11626		        (ctxt->sax->cdataBlock != NULL) &&
11627		        (!ctxt->disableSAX)) {
11628			/*
11629			 * Special case to provide identical behaviour
11630			 * between pull and push parsers on enpty CDATA
11631			 * sections
11632			 */
11633			 if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11634			     (!strncmp((const char *)&ctxt->input->cur[-9],
11635			               "<![CDATA[", 9)))
11636			     ctxt->sax->cdataBlock(ctxt->userData,
11637			                           BAD_CAST "", 0);
11638		    } else if ((ctxt->sax != NULL) && (base > 0) &&
11639			(!ctxt->disableSAX)) {
11640			if (ctxt->sax->cdataBlock != NULL)
11641			    ctxt->sax->cdataBlock(ctxt->userData,
11642						  ctxt->input->cur, base);
11643			else if (ctxt->sax->characters != NULL)
11644			    ctxt->sax->characters(ctxt->userData,
11645						  ctxt->input->cur, base);
11646		    }
11647		    if (ctxt->instate == XML_PARSER_EOF)
11648			goto done;
11649		    SKIPL(base + 3);
11650		    ctxt->checkIndex = 0;
11651		    ctxt->instate = XML_PARSER_CONTENT;
11652#ifdef DEBUG_PUSH
11653		    xmlGenericError(xmlGenericErrorContext,
11654			    "PP: entering CONTENT\n");
11655#endif
11656		}
11657		break;
11658	    }
11659            case XML_PARSER_MISC:
11660		SKIP_BLANKS;
11661		if (ctxt->input->buf == NULL)
11662		    avail = ctxt->input->length -
11663		            (ctxt->input->cur - ctxt->input->base);
11664		else
11665		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11666		            (ctxt->input->cur - ctxt->input->base);
11667		if (avail < 2)
11668		    goto done;
11669		cur = ctxt->input->cur[0];
11670		next = ctxt->input->cur[1];
11671	        if ((cur == '<') && (next == '?')) {
11672		    if ((!terminate) &&
11673		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11674                        ctxt->progressive = XML_PARSER_PI;
11675			goto done;
11676                    }
11677#ifdef DEBUG_PUSH
11678		    xmlGenericError(xmlGenericErrorContext,
11679			    "PP: Parsing PI\n");
11680#endif
11681		    xmlParsePI(ctxt);
11682		    if (ctxt->instate == XML_PARSER_EOF)
11683			goto done;
11684		    ctxt->instate = XML_PARSER_MISC;
11685                    ctxt->progressive = 1;
11686		    ctxt->checkIndex = 0;
11687		} else if ((cur == '<') && (next == '!') &&
11688		    (ctxt->input->cur[2] == '-') &&
11689		    (ctxt->input->cur[3] == '-')) {
11690		    if ((!terminate) &&
11691		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11692                        ctxt->progressive = XML_PARSER_COMMENT;
11693			goto done;
11694                    }
11695#ifdef DEBUG_PUSH
11696		    xmlGenericError(xmlGenericErrorContext,
11697			    "PP: Parsing Comment\n");
11698#endif
11699		    xmlParseComment(ctxt);
11700		    if (ctxt->instate == XML_PARSER_EOF)
11701			goto done;
11702		    ctxt->instate = XML_PARSER_MISC;
11703                    ctxt->progressive = 1;
11704		    ctxt->checkIndex = 0;
11705		} else if ((cur == '<') && (next == '!') &&
11706		    (ctxt->input->cur[2] == 'D') &&
11707		    (ctxt->input->cur[3] == 'O') &&
11708		    (ctxt->input->cur[4] == 'C') &&
11709		    (ctxt->input->cur[5] == 'T') &&
11710		    (ctxt->input->cur[6] == 'Y') &&
11711		    (ctxt->input->cur[7] == 'P') &&
11712		    (ctxt->input->cur[8] == 'E')) {
11713		    if ((!terminate) &&
11714		        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
11715                        ctxt->progressive = XML_PARSER_DTD;
11716			goto done;
11717                    }
11718#ifdef DEBUG_PUSH
11719		    xmlGenericError(xmlGenericErrorContext,
11720			    "PP: Parsing internal subset\n");
11721#endif
11722		    ctxt->inSubset = 1;
11723                    ctxt->progressive = 0;
11724		    ctxt->checkIndex = 0;
11725		    xmlParseDocTypeDecl(ctxt);
11726		    if (ctxt->instate == XML_PARSER_EOF)
11727			goto done;
11728		    if (RAW == '[') {
11729			ctxt->instate = XML_PARSER_DTD;
11730#ifdef DEBUG_PUSH
11731			xmlGenericError(xmlGenericErrorContext,
11732				"PP: entering DTD\n");
11733#endif
11734		    } else {
11735			/*
11736			 * Create and update the external subset.
11737			 */
11738			ctxt->inSubset = 2;
11739			if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11740			    (ctxt->sax->externalSubset != NULL))
11741			    ctxt->sax->externalSubset(ctxt->userData,
11742				    ctxt->intSubName, ctxt->extSubSystem,
11743				    ctxt->extSubURI);
11744			ctxt->inSubset = 0;
11745			xmlCleanSpecialAttr(ctxt);
11746			ctxt->instate = XML_PARSER_PROLOG;
11747#ifdef DEBUG_PUSH
11748			xmlGenericError(xmlGenericErrorContext,
11749				"PP: entering PROLOG\n");
11750#endif
11751		    }
11752		} else if ((cur == '<') && (next == '!') &&
11753		           (avail < 9)) {
11754		    goto done;
11755		} else {
11756		    ctxt->instate = XML_PARSER_START_TAG;
11757		    ctxt->progressive = XML_PARSER_START_TAG;
11758		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11759#ifdef DEBUG_PUSH
11760		    xmlGenericError(xmlGenericErrorContext,
11761			    "PP: entering START_TAG\n");
11762#endif
11763		}
11764		break;
11765            case XML_PARSER_PROLOG:
11766		SKIP_BLANKS;
11767		if (ctxt->input->buf == NULL)
11768		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11769		else
11770		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11771                            (ctxt->input->cur - ctxt->input->base);
11772		if (avail < 2)
11773		    goto done;
11774		cur = ctxt->input->cur[0];
11775		next = ctxt->input->cur[1];
11776	        if ((cur == '<') && (next == '?')) {
11777		    if ((!terminate) &&
11778		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11779                        ctxt->progressive = XML_PARSER_PI;
11780			goto done;
11781                    }
11782#ifdef DEBUG_PUSH
11783		    xmlGenericError(xmlGenericErrorContext,
11784			    "PP: Parsing PI\n");
11785#endif
11786		    xmlParsePI(ctxt);
11787		    if (ctxt->instate == XML_PARSER_EOF)
11788			goto done;
11789		    ctxt->instate = XML_PARSER_PROLOG;
11790                    ctxt->progressive = 1;
11791		} else if ((cur == '<') && (next == '!') &&
11792		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11793		    if ((!terminate) &&
11794		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11795                        ctxt->progressive = XML_PARSER_COMMENT;
11796			goto done;
11797                    }
11798#ifdef DEBUG_PUSH
11799		    xmlGenericError(xmlGenericErrorContext,
11800			    "PP: Parsing Comment\n");
11801#endif
11802		    xmlParseComment(ctxt);
11803		    if (ctxt->instate == XML_PARSER_EOF)
11804			goto done;
11805		    ctxt->instate = XML_PARSER_PROLOG;
11806                    ctxt->progressive = 1;
11807		} else if ((cur == '<') && (next == '!') &&
11808		           (avail < 4)) {
11809		    goto done;
11810		} else {
11811		    ctxt->instate = XML_PARSER_START_TAG;
11812		    if (ctxt->progressive == 0)
11813			ctxt->progressive = XML_PARSER_START_TAG;
11814		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11815#ifdef DEBUG_PUSH
11816		    xmlGenericError(xmlGenericErrorContext,
11817			    "PP: entering START_TAG\n");
11818#endif
11819		}
11820		break;
11821            case XML_PARSER_EPILOG:
11822		SKIP_BLANKS;
11823		if (ctxt->input->buf == NULL)
11824		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11825		else
11826		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11827                            (ctxt->input->cur - ctxt->input->base);
11828		if (avail < 2)
11829		    goto done;
11830		cur = ctxt->input->cur[0];
11831		next = ctxt->input->cur[1];
11832	        if ((cur == '<') && (next == '?')) {
11833		    if ((!terminate) &&
11834		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11835                        ctxt->progressive = XML_PARSER_PI;
11836			goto done;
11837                    }
11838#ifdef DEBUG_PUSH
11839		    xmlGenericError(xmlGenericErrorContext,
11840			    "PP: Parsing PI\n");
11841#endif
11842		    xmlParsePI(ctxt);
11843		    if (ctxt->instate == XML_PARSER_EOF)
11844			goto done;
11845		    ctxt->instate = XML_PARSER_EPILOG;
11846                    ctxt->progressive = 1;
11847		} else if ((cur == '<') && (next == '!') &&
11848		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11849		    if ((!terminate) &&
11850		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11851                        ctxt->progressive = XML_PARSER_COMMENT;
11852			goto done;
11853                    }
11854#ifdef DEBUG_PUSH
11855		    xmlGenericError(xmlGenericErrorContext,
11856			    "PP: Parsing Comment\n");
11857#endif
11858		    xmlParseComment(ctxt);
11859		    if (ctxt->instate == XML_PARSER_EOF)
11860			goto done;
11861		    ctxt->instate = XML_PARSER_EPILOG;
11862                    ctxt->progressive = 1;
11863		} else if ((cur == '<') && (next == '!') &&
11864		           (avail < 4)) {
11865		    goto done;
11866		} else {
11867		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11868		    ctxt->instate = XML_PARSER_EOF;
11869#ifdef DEBUG_PUSH
11870		    xmlGenericError(xmlGenericErrorContext,
11871			    "PP: entering EOF\n");
11872#endif
11873		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11874			ctxt->sax->endDocument(ctxt->userData);
11875		    goto done;
11876		}
11877		break;
11878            case XML_PARSER_DTD: {
11879	        /*
11880		 * Sorry but progressive parsing of the internal subset
11881		 * is not expected to be supported. We first check that
11882		 * the full content of the internal subset is available and
11883		 * the parsing is launched only at that point.
11884		 * Internal subset ends up with "']' S? '>'" in an unescaped
11885		 * section and not in a ']]>' sequence which are conditional
11886		 * sections (whoever argued to keep that crap in XML deserve
11887		 * a place in hell !).
11888		 */
11889		int base, i;
11890		xmlChar *buf;
11891	        xmlChar quote = 0;
11892                size_t use;
11893
11894		base = ctxt->input->cur - ctxt->input->base;
11895		if (base < 0) return(0);
11896		if (ctxt->checkIndex > base)
11897		    base = ctxt->checkIndex;
11898		buf = xmlBufContent(ctxt->input->buf->buffer);
11899                use = xmlBufUse(ctxt->input->buf->buffer);
11900		for (;(unsigned int) base < use; base++) {
11901		    if (quote != 0) {
11902		        if (buf[base] == quote)
11903			    quote = 0;
11904			continue;
11905		    }
11906		    if ((quote == 0) && (buf[base] == '<')) {
11907		        int found  = 0;
11908			/* special handling of comments */
11909		        if (((unsigned int) base + 4 < use) &&
11910			    (buf[base + 1] == '!') &&
11911			    (buf[base + 2] == '-') &&
11912			    (buf[base + 3] == '-')) {
11913			    for (;(unsigned int) base + 3 < use; base++) {
11914				if ((buf[base] == '-') &&
11915				    (buf[base + 1] == '-') &&
11916				    (buf[base + 2] == '>')) {
11917				    found = 1;
11918				    base += 2;
11919				    break;
11920				}
11921		            }
11922			    if (!found) {
11923#if 0
11924			        fprintf(stderr, "unfinished comment\n");
11925#endif
11926			        break; /* for */
11927		            }
11928		            continue;
11929			}
11930		    }
11931		    if (buf[base] == '"') {
11932		        quote = '"';
11933			continue;
11934		    }
11935		    if (buf[base] == '\'') {
11936		        quote = '\'';
11937			continue;
11938		    }
11939		    if (buf[base] == ']') {
11940#if 0
11941		        fprintf(stderr, "%c%c%c%c: ", buf[base],
11942			        buf[base + 1], buf[base + 2], buf[base + 3]);
11943#endif
11944		        if ((unsigned int) base +1 >= use)
11945			    break;
11946			if (buf[base + 1] == ']') {
11947			    /* conditional crap, skip both ']' ! */
11948			    base++;
11949			    continue;
11950			}
11951		        for (i = 1; (unsigned int) base + i < use; i++) {
11952			    if (buf[base + i] == '>') {
11953#if 0
11954			        fprintf(stderr, "found\n");
11955#endif
11956			        goto found_end_int_subset;
11957			    }
11958			    if (!IS_BLANK_CH(buf[base + i])) {
11959#if 0
11960			        fprintf(stderr, "not found\n");
11961#endif
11962			        goto not_end_of_int_subset;
11963			    }
11964			}
11965#if 0
11966			fprintf(stderr, "end of stream\n");
11967#endif
11968		        break;
11969
11970		    }
11971not_end_of_int_subset:
11972                    continue; /* for */
11973		}
11974		/*
11975		 * We didn't found the end of the Internal subset
11976		 */
11977                if (quote == 0)
11978                    ctxt->checkIndex = base;
11979                else
11980                    ctxt->checkIndex = 0;
11981#ifdef DEBUG_PUSH
11982		if (next == 0)
11983		    xmlGenericError(xmlGenericErrorContext,
11984			    "PP: lookup of int subset end filed\n");
11985#endif
11986	        goto done;
11987
11988found_end_int_subset:
11989                ctxt->checkIndex = 0;
11990		xmlParseInternalSubset(ctxt);
11991		if (ctxt->instate == XML_PARSER_EOF)
11992		    goto done;
11993		ctxt->inSubset = 2;
11994		if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11995		    (ctxt->sax->externalSubset != NULL))
11996		    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11997			    ctxt->extSubSystem, ctxt->extSubURI);
11998		ctxt->inSubset = 0;
11999		xmlCleanSpecialAttr(ctxt);
12000		if (ctxt->instate == XML_PARSER_EOF)
12001		    goto done;
12002		ctxt->instate = XML_PARSER_PROLOG;
12003		ctxt->checkIndex = 0;
12004#ifdef DEBUG_PUSH
12005		xmlGenericError(xmlGenericErrorContext,
12006			"PP: entering PROLOG\n");
12007#endif
12008                break;
12009	    }
12010            case XML_PARSER_COMMENT:
12011		xmlGenericError(xmlGenericErrorContext,
12012			"PP: internal error, state == COMMENT\n");
12013		ctxt->instate = XML_PARSER_CONTENT;
12014#ifdef DEBUG_PUSH
12015		xmlGenericError(xmlGenericErrorContext,
12016			"PP: entering CONTENT\n");
12017#endif
12018		break;
12019            case XML_PARSER_IGNORE:
12020		xmlGenericError(xmlGenericErrorContext,
12021			"PP: internal error, state == IGNORE");
12022	        ctxt->instate = XML_PARSER_DTD;
12023#ifdef DEBUG_PUSH
12024		xmlGenericError(xmlGenericErrorContext,
12025			"PP: entering DTD\n");
12026#endif
12027	        break;
12028            case XML_PARSER_PI:
12029		xmlGenericError(xmlGenericErrorContext,
12030			"PP: internal error, state == PI\n");
12031		ctxt->instate = XML_PARSER_CONTENT;
12032#ifdef DEBUG_PUSH
12033		xmlGenericError(xmlGenericErrorContext,
12034			"PP: entering CONTENT\n");
12035#endif
12036		break;
12037            case XML_PARSER_ENTITY_DECL:
12038		xmlGenericError(xmlGenericErrorContext,
12039			"PP: internal error, state == ENTITY_DECL\n");
12040		ctxt->instate = XML_PARSER_DTD;
12041#ifdef DEBUG_PUSH
12042		xmlGenericError(xmlGenericErrorContext,
12043			"PP: entering DTD\n");
12044#endif
12045		break;
12046            case XML_PARSER_ENTITY_VALUE:
12047		xmlGenericError(xmlGenericErrorContext,
12048			"PP: internal error, state == ENTITY_VALUE\n");
12049		ctxt->instate = XML_PARSER_CONTENT;
12050#ifdef DEBUG_PUSH
12051		xmlGenericError(xmlGenericErrorContext,
12052			"PP: entering DTD\n");
12053#endif
12054		break;
12055            case XML_PARSER_ATTRIBUTE_VALUE:
12056		xmlGenericError(xmlGenericErrorContext,
12057			"PP: internal error, state == ATTRIBUTE_VALUE\n");
12058		ctxt->instate = XML_PARSER_START_TAG;
12059#ifdef DEBUG_PUSH
12060		xmlGenericError(xmlGenericErrorContext,
12061			"PP: entering START_TAG\n");
12062#endif
12063		break;
12064            case XML_PARSER_SYSTEM_LITERAL:
12065		xmlGenericError(xmlGenericErrorContext,
12066			"PP: internal error, state == SYSTEM_LITERAL\n");
12067		ctxt->instate = XML_PARSER_START_TAG;
12068#ifdef DEBUG_PUSH
12069		xmlGenericError(xmlGenericErrorContext,
12070			"PP: entering START_TAG\n");
12071#endif
12072		break;
12073            case XML_PARSER_PUBLIC_LITERAL:
12074		xmlGenericError(xmlGenericErrorContext,
12075			"PP: internal error, state == PUBLIC_LITERAL\n");
12076		ctxt->instate = XML_PARSER_START_TAG;
12077#ifdef DEBUG_PUSH
12078		xmlGenericError(xmlGenericErrorContext,
12079			"PP: entering START_TAG\n");
12080#endif
12081		break;
12082	}
12083    }
12084done:
12085#ifdef DEBUG_PUSH
12086    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
12087#endif
12088    return(ret);
12089encoding_error:
12090    {
12091        char buffer[150];
12092
12093	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12094			ctxt->input->cur[0], ctxt->input->cur[1],
12095			ctxt->input->cur[2], ctxt->input->cur[3]);
12096	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12097		     "Input is not proper UTF-8, indicate encoding !\n%s",
12098		     BAD_CAST buffer, NULL);
12099    }
12100    return(0);
12101}
12102
12103/**
12104 * xmlParseCheckTransition:
12105 * @ctxt:  an XML parser context
12106 * @chunk:  a char array
12107 * @size:  the size in byte of the chunk
12108 *
12109 * Check depending on the current parser state if the chunk given must be
12110 * processed immediately or one need more data to advance on parsing.
12111 *
12112 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
12113 */
12114static int
12115xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
12116    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
12117        return(-1);
12118    if (ctxt->instate == XML_PARSER_START_TAG) {
12119        if (memchr(chunk, '>', size) != NULL)
12120            return(1);
12121        return(0);
12122    }
12123    if (ctxt->progressive == XML_PARSER_COMMENT) {
12124        if (memchr(chunk, '>', size) != NULL)
12125            return(1);
12126        return(0);
12127    }
12128    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
12129        if (memchr(chunk, '>', size) != NULL)
12130            return(1);
12131        return(0);
12132    }
12133    if (ctxt->progressive == XML_PARSER_PI) {
12134        if (memchr(chunk, '>', size) != NULL)
12135            return(1);
12136        return(0);
12137    }
12138    if (ctxt->instate == XML_PARSER_END_TAG) {
12139        if (memchr(chunk, '>', size) != NULL)
12140            return(1);
12141        return(0);
12142    }
12143    if ((ctxt->progressive == XML_PARSER_DTD) ||
12144        (ctxt->instate == XML_PARSER_DTD)) {
12145        if (memchr(chunk, '>', size) != NULL)
12146            return(1);
12147        return(0);
12148    }
12149    return(1);
12150}
12151
12152/**
12153 * xmlParseChunk:
12154 * @ctxt:  an XML parser context
12155 * @chunk:  an char array
12156 * @size:  the size in byte of the chunk
12157 * @terminate:  last chunk indicator
12158 *
12159 * Parse a Chunk of memory
12160 *
12161 * Returns zero if no error, the xmlParserErrors otherwise.
12162 */
12163int
12164xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12165              int terminate) {
12166    int end_in_lf = 0;
12167    int remain = 0;
12168    size_t old_avail = 0;
12169    size_t avail = 0;
12170
12171    if (ctxt == NULL)
12172        return(XML_ERR_INTERNAL_ERROR);
12173    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12174        return(ctxt->errNo);
12175    if (ctxt->instate == XML_PARSER_EOF)
12176        return(-1);
12177    if (ctxt->instate == XML_PARSER_START)
12178        xmlDetectSAX2(ctxt);
12179    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12180        (chunk[size - 1] == '\r')) {
12181	end_in_lf = 1;
12182	size--;
12183    }
12184
12185xmldecl_done:
12186
12187    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12188        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12189	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12190	size_t cur = ctxt->input->cur - ctxt->input->base;
12191	int res;
12192
12193        old_avail = xmlBufUse(ctxt->input->buf->buffer);
12194        /*
12195         * Specific handling if we autodetected an encoding, we should not
12196         * push more than the first line ... which depend on the encoding
12197         * And only push the rest once the final encoding was detected
12198         */
12199        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
12200            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
12201            unsigned int len = 45;
12202
12203            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12204                               BAD_CAST "UTF-16")) ||
12205                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12206                               BAD_CAST "UTF16")))
12207                len = 90;
12208            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12209                                    BAD_CAST "UCS-4")) ||
12210                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12211                                    BAD_CAST "UCS4")))
12212                len = 180;
12213
12214            if (ctxt->input->buf->rawconsumed < len)
12215                len -= ctxt->input->buf->rawconsumed;
12216
12217            /*
12218             * Change size for reading the initial declaration only
12219             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
12220             * will blindly copy extra bytes from memory.
12221             */
12222            if ((unsigned int) size > len) {
12223                remain = size - len;
12224                size = len;
12225            } else {
12226                remain = 0;
12227            }
12228        }
12229	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12230	if (res < 0) {
12231	    ctxt->errNo = XML_PARSER_EOF;
12232	    ctxt->disableSAX = 1;
12233	    return (XML_PARSER_EOF);
12234	}
12235        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12236#ifdef DEBUG_PUSH
12237	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12238#endif
12239
12240    } else if (ctxt->instate != XML_PARSER_EOF) {
12241	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
12242	    xmlParserInputBufferPtr in = ctxt->input->buf;
12243	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
12244		    (in->raw != NULL)) {
12245		int nbchars;
12246		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
12247		size_t current = ctxt->input->cur - ctxt->input->base;
12248
12249		nbchars = xmlCharEncInput(in, terminate);
12250		if (nbchars < 0) {
12251		    /* TODO 2.6.0 */
12252		    xmlGenericError(xmlGenericErrorContext,
12253				    "xmlParseChunk: encoder error\n");
12254		    return(XML_ERR_INVALID_ENCODING);
12255		}
12256		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
12257	    }
12258	}
12259    }
12260    if (remain != 0) {
12261        xmlParseTryOrFinish(ctxt, 0);
12262    } else {
12263        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
12264            avail = xmlBufUse(ctxt->input->buf->buffer);
12265        /*
12266         * Depending on the current state it may not be such
12267         * a good idea to try parsing if there is nothing in the chunk
12268         * which would be worth doing a parser state transition and we
12269         * need to wait for more data
12270         */
12271        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
12272            (old_avail == 0) || (avail == 0) ||
12273            (xmlParseCheckTransition(ctxt,
12274                       (const char *)&ctxt->input->base[old_avail],
12275                                     avail - old_avail)))
12276            xmlParseTryOrFinish(ctxt, terminate);
12277    }
12278    if (ctxt->instate == XML_PARSER_EOF)
12279        return(ctxt->errNo);
12280
12281    if ((ctxt->input != NULL) &&
12282         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12283         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12284        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12285        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12286        ctxt->instate = XML_PARSER_EOF;
12287    }
12288    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12289        return(ctxt->errNo);
12290
12291    if (remain != 0) {
12292        chunk += size;
12293        size = remain;
12294        remain = 0;
12295        goto xmldecl_done;
12296    }
12297    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12298        (ctxt->input->buf != NULL)) {
12299	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
12300					 ctxt->input);
12301	size_t current = ctxt->input->cur - ctxt->input->base;
12302
12303	xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12304
12305	xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
12306			      base, current);
12307    }
12308    if (terminate) {
12309	/*
12310	 * Check for termination
12311	 */
12312	int cur_avail = 0;
12313
12314	if (ctxt->input != NULL) {
12315	    if (ctxt->input->buf == NULL)
12316		cur_avail = ctxt->input->length -
12317			    (ctxt->input->cur - ctxt->input->base);
12318	    else
12319		cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
12320			              (ctxt->input->cur - ctxt->input->base);
12321	}
12322
12323	if ((ctxt->instate != XML_PARSER_EOF) &&
12324	    (ctxt->instate != XML_PARSER_EPILOG)) {
12325	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12326	}
12327	if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
12328	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12329	}
12330	if (ctxt->instate != XML_PARSER_EOF) {
12331	    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12332		ctxt->sax->endDocument(ctxt->userData);
12333	}
12334	ctxt->instate = XML_PARSER_EOF;
12335    }
12336    if (ctxt->wellFormed == 0)
12337	return((xmlParserErrors) ctxt->errNo);
12338    else
12339        return(0);
12340}
12341
12342/************************************************************************
12343 *									*
12344 *		I/O front end functions to the parser			*
12345 *									*
12346 ************************************************************************/
12347
12348/**
12349 * xmlCreatePushParserCtxt:
12350 * @sax:  a SAX handler
12351 * @user_data:  The user data returned on SAX callbacks
12352 * @chunk:  a pointer to an array of chars
12353 * @size:  number of chars in the array
12354 * @filename:  an optional file name or URI
12355 *
12356 * Create a parser context for using the XML parser in push mode.
12357 * If @buffer and @size are non-NULL, the data is used to detect
12358 * the encoding.  The remaining characters will be parsed so they
12359 * don't need to be fed in again through xmlParseChunk.
12360 * To allow content encoding detection, @size should be >= 4
12361 * The value of @filename is used for fetching external entities
12362 * and error/warning reports.
12363 *
12364 * Returns the new parser context or NULL
12365 */
12366
12367xmlParserCtxtPtr
12368xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12369                        const char *chunk, int size, const char *filename) {
12370    xmlParserCtxtPtr ctxt;
12371    xmlParserInputPtr inputStream;
12372    xmlParserInputBufferPtr buf;
12373    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
12374
12375    /*
12376     * plug some encoding conversion routines
12377     */
12378    if ((chunk != NULL) && (size >= 4))
12379	enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
12380
12381    buf = xmlAllocParserInputBuffer(enc);
12382    if (buf == NULL) return(NULL);
12383
12384    ctxt = xmlNewParserCtxt();
12385    if (ctxt == NULL) {
12386        xmlErrMemory(NULL, "creating parser: out of memory\n");
12387	xmlFreeParserInputBuffer(buf);
12388	return(NULL);
12389    }
12390    ctxt->dictNames = 1;
12391    ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
12392    if (ctxt->pushTab == NULL) {
12393        xmlErrMemory(ctxt, NULL);
12394	xmlFreeParserInputBuffer(buf);
12395	xmlFreeParserCtxt(ctxt);
12396	return(NULL);
12397    }
12398    if (sax != NULL) {
12399#ifdef LIBXML_SAX1_ENABLED
12400	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
12401#endif /* LIBXML_SAX1_ENABLED */
12402	    xmlFree(ctxt->sax);
12403	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
12404	if (ctxt->sax == NULL) {
12405	    xmlErrMemory(ctxt, NULL);
12406	    xmlFreeParserInputBuffer(buf);
12407	    xmlFreeParserCtxt(ctxt);
12408	    return(NULL);
12409	}
12410	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
12411	if (sax->initialized == XML_SAX2_MAGIC)
12412	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
12413	else
12414	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12415	if (user_data != NULL)
12416	    ctxt->userData = user_data;
12417    }
12418    if (filename == NULL) {
12419	ctxt->directory = NULL;
12420    } else {
12421        ctxt->directory = xmlParserGetDirectory(filename);
12422    }
12423
12424    inputStream = xmlNewInputStream(ctxt);
12425    if (inputStream == NULL) {
12426	xmlFreeParserCtxt(ctxt);
12427	xmlFreeParserInputBuffer(buf);
12428	return(NULL);
12429    }
12430
12431    if (filename == NULL)
12432	inputStream->filename = NULL;
12433    else {
12434	inputStream->filename = (char *)
12435	    xmlCanonicPath((const xmlChar *) filename);
12436	if (inputStream->filename == NULL) {
12437	    xmlFreeParserCtxt(ctxt);
12438	    xmlFreeParserInputBuffer(buf);
12439	    return(NULL);
12440	}
12441    }
12442    inputStream->buf = buf;
12443    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12444    inputPush(ctxt, inputStream);
12445
12446    /*
12447     * If the caller didn't provide an initial 'chunk' for determining
12448     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
12449     * that it can be automatically determined later
12450     */
12451    if ((size == 0) || (chunk == NULL)) {
12452	ctxt->charset = XML_CHAR_ENCODING_NONE;
12453    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12454	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12455	size_t cur = ctxt->input->cur - ctxt->input->base;
12456
12457	xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12458
12459        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12460#ifdef DEBUG_PUSH
12461	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12462#endif
12463    }
12464
12465    if (enc != XML_CHAR_ENCODING_NONE) {
12466        xmlSwitchEncoding(ctxt, enc);
12467    }
12468
12469    return(ctxt);
12470}
12471#endif /* LIBXML_PUSH_ENABLED */
12472
12473/**
12474 * xmlStopParser:
12475 * @ctxt:  an XML parser context
12476 *
12477 * Blocks further parser processing
12478 */
12479void
12480xmlStopParser(xmlParserCtxtPtr ctxt) {
12481    if (ctxt == NULL)
12482        return;
12483    ctxt->instate = XML_PARSER_EOF;
12484    ctxt->errNo = XML_ERR_USER_STOP;
12485    ctxt->disableSAX = 1;
12486    if (ctxt->input != NULL) {
12487	ctxt->input->cur = BAD_CAST"";
12488	ctxt->input->base = ctxt->input->cur;
12489    }
12490}
12491
12492/**
12493 * xmlCreateIOParserCtxt:
12494 * @sax:  a SAX handler
12495 * @user_data:  The user data returned on SAX callbacks
12496 * @ioread:  an I/O read function
12497 * @ioclose:  an I/O close function
12498 * @ioctx:  an I/O handler
12499 * @enc:  the charset encoding if known
12500 *
12501 * Create a parser context for using the XML parser with an existing
12502 * I/O stream
12503 *
12504 * Returns the new parser context or NULL
12505 */
12506xmlParserCtxtPtr
12507xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12508	xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12509	void *ioctx, xmlCharEncoding enc) {
12510    xmlParserCtxtPtr ctxt;
12511    xmlParserInputPtr inputStream;
12512    xmlParserInputBufferPtr buf;
12513
12514    if (ioread == NULL) return(NULL);
12515
12516    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12517    if (buf == NULL) {
12518        if (ioclose != NULL)
12519            ioclose(ioctx);
12520        return (NULL);
12521    }
12522
12523    ctxt = xmlNewParserCtxt();
12524    if (ctxt == NULL) {
12525	xmlFreeParserInputBuffer(buf);
12526	return(NULL);
12527    }
12528    if (sax != NULL) {
12529#ifdef LIBXML_SAX1_ENABLED
12530	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
12531#endif /* LIBXML_SAX1_ENABLED */
12532	    xmlFree(ctxt->sax);
12533	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
12534	if (ctxt->sax == NULL) {
12535	    xmlErrMemory(ctxt, NULL);
12536	    xmlFreeParserCtxt(ctxt);
12537	    return(NULL);
12538	}
12539	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
12540	if (sax->initialized == XML_SAX2_MAGIC)
12541	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
12542	else
12543	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12544	if (user_data != NULL)
12545	    ctxt->userData = user_data;
12546    }
12547
12548    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12549    if (inputStream == NULL) {
12550	xmlFreeParserCtxt(ctxt);
12551	return(NULL);
12552    }
12553    inputPush(ctxt, inputStream);
12554
12555    return(ctxt);
12556}
12557
12558#ifdef LIBXML_VALID_ENABLED
12559/************************************************************************
12560 *									*
12561 *		Front ends when parsing a DTD				*
12562 *									*
12563 ************************************************************************/
12564
12565/**
12566 * xmlIOParseDTD:
12567 * @sax:  the SAX handler block or NULL
12568 * @input:  an Input Buffer
12569 * @enc:  the charset encoding if known
12570 *
12571 * Load and parse a DTD
12572 *
12573 * Returns the resulting xmlDtdPtr or NULL in case of error.
12574 * @input will be freed by the function in any case.
12575 */
12576
12577xmlDtdPtr
12578xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12579	      xmlCharEncoding enc) {
12580    xmlDtdPtr ret = NULL;
12581    xmlParserCtxtPtr ctxt;
12582    xmlParserInputPtr pinput = NULL;
12583    xmlChar start[4];
12584
12585    if (input == NULL)
12586	return(NULL);
12587
12588    ctxt = xmlNewParserCtxt();
12589    if (ctxt == NULL) {
12590        xmlFreeParserInputBuffer(input);
12591	return(NULL);
12592    }
12593
12594    /*
12595     * Set-up the SAX context
12596     */
12597    if (sax != NULL) {
12598	if (ctxt->sax != NULL)
12599	    xmlFree(ctxt->sax);
12600        ctxt->sax = sax;
12601        ctxt->userData = ctxt;
12602    }
12603    xmlDetectSAX2(ctxt);
12604
12605    /*
12606     * generate a parser input from the I/O handler
12607     */
12608
12609    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12610    if (pinput == NULL) {
12611        if (sax != NULL) ctxt->sax = NULL;
12612        xmlFreeParserInputBuffer(input);
12613	xmlFreeParserCtxt(ctxt);
12614	return(NULL);
12615    }
12616
12617    /*
12618     * plug some encoding conversion routines here.
12619     */
12620    if (xmlPushInput(ctxt, pinput) < 0) {
12621        if (sax != NULL) ctxt->sax = NULL;
12622	xmlFreeParserCtxt(ctxt);
12623	return(NULL);
12624    }
12625    if (enc != XML_CHAR_ENCODING_NONE) {
12626        xmlSwitchEncoding(ctxt, enc);
12627    }
12628
12629    pinput->filename = NULL;
12630    pinput->line = 1;
12631    pinput->col = 1;
12632    pinput->base = ctxt->input->cur;
12633    pinput->cur = ctxt->input->cur;
12634    pinput->free = NULL;
12635
12636    /*
12637     * let's parse that entity knowing it's an external subset.
12638     */
12639    ctxt->inSubset = 2;
12640    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12641    if (ctxt->myDoc == NULL) {
12642	xmlErrMemory(ctxt, "New Doc failed");
12643	return(NULL);
12644    }
12645    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12646    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12647	                               BAD_CAST "none", BAD_CAST "none");
12648
12649    if ((enc == XML_CHAR_ENCODING_NONE) &&
12650        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12651	/*
12652	 * Get the 4 first bytes and decode the charset
12653	 * if enc != XML_CHAR_ENCODING_NONE
12654	 * plug some encoding conversion routines.
12655	 */
12656	start[0] = RAW;
12657	start[1] = NXT(1);
12658	start[2] = NXT(2);
12659	start[3] = NXT(3);
12660	enc = xmlDetectCharEncoding(start, 4);
12661	if (enc != XML_CHAR_ENCODING_NONE) {
12662	    xmlSwitchEncoding(ctxt, enc);
12663	}
12664    }
12665
12666    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12667
12668    if (ctxt->myDoc != NULL) {
12669	if (ctxt->wellFormed) {
12670	    ret = ctxt->myDoc->extSubset;
12671	    ctxt->myDoc->extSubset = NULL;
12672	    if (ret != NULL) {
12673		xmlNodePtr tmp;
12674
12675		ret->doc = NULL;
12676		tmp = ret->children;
12677		while (tmp != NULL) {
12678		    tmp->doc = NULL;
12679		    tmp = tmp->next;
12680		}
12681	    }
12682	} else {
12683	    ret = NULL;
12684	}
12685        xmlFreeDoc(ctxt->myDoc);
12686        ctxt->myDoc = NULL;
12687    }
12688    if (sax != NULL) ctxt->sax = NULL;
12689    xmlFreeParserCtxt(ctxt);
12690
12691    return(ret);
12692}
12693
12694/**
12695 * xmlSAXParseDTD:
12696 * @sax:  the SAX handler block
12697 * @ExternalID:  a NAME* containing the External ID of the DTD
12698 * @SystemID:  a NAME* containing the URL to the DTD
12699 *
12700 * Load and parse an external subset.
12701 *
12702 * Returns the resulting xmlDtdPtr or NULL in case of error.
12703 */
12704
12705xmlDtdPtr
12706xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12707                          const xmlChar *SystemID) {
12708    xmlDtdPtr ret = NULL;
12709    xmlParserCtxtPtr ctxt;
12710    xmlParserInputPtr input = NULL;
12711    xmlCharEncoding enc;
12712    xmlChar* systemIdCanonic;
12713
12714    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12715
12716    ctxt = xmlNewParserCtxt();
12717    if (ctxt == NULL) {
12718	return(NULL);
12719    }
12720
12721    /*
12722     * Set-up the SAX context
12723     */
12724    if (sax != NULL) {
12725	if (ctxt->sax != NULL)
12726	    xmlFree(ctxt->sax);
12727        ctxt->sax = sax;
12728        ctxt->userData = ctxt;
12729    }
12730
12731    /*
12732     * Canonicalise the system ID
12733     */
12734    systemIdCanonic = xmlCanonicPath(SystemID);
12735    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12736	xmlFreeParserCtxt(ctxt);
12737	return(NULL);
12738    }
12739
12740    /*
12741     * Ask the Entity resolver to load the damn thing
12742     */
12743
12744    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12745	input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12746	                                 systemIdCanonic);
12747    if (input == NULL) {
12748        if (sax != NULL) ctxt->sax = NULL;
12749	xmlFreeParserCtxt(ctxt);
12750	if (systemIdCanonic != NULL)
12751	    xmlFree(systemIdCanonic);
12752	return(NULL);
12753    }
12754
12755    /*
12756     * plug some encoding conversion routines here.
12757     */
12758    if (xmlPushInput(ctxt, input) < 0) {
12759        if (sax != NULL) ctxt->sax = NULL;
12760	xmlFreeParserCtxt(ctxt);
12761	if (systemIdCanonic != NULL)
12762	    xmlFree(systemIdCanonic);
12763	return(NULL);
12764    }
12765    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12766	enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12767	xmlSwitchEncoding(ctxt, enc);
12768    }
12769
12770    if (input->filename == NULL)
12771	input->filename = (char *) systemIdCanonic;
12772    else
12773	xmlFree(systemIdCanonic);
12774    input->line = 1;
12775    input->col = 1;
12776    input->base = ctxt->input->cur;
12777    input->cur = ctxt->input->cur;
12778    input->free = NULL;
12779
12780    /*
12781     * let's parse that entity knowing it's an external subset.
12782     */
12783    ctxt->inSubset = 2;
12784    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12785    if (ctxt->myDoc == NULL) {
12786	xmlErrMemory(ctxt, "New Doc failed");
12787        if (sax != NULL) ctxt->sax = NULL;
12788	xmlFreeParserCtxt(ctxt);
12789	return(NULL);
12790    }
12791    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12792    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12793	                               ExternalID, SystemID);
12794    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12795
12796    if (ctxt->myDoc != NULL) {
12797	if (ctxt->wellFormed) {
12798	    ret = ctxt->myDoc->extSubset;
12799	    ctxt->myDoc->extSubset = NULL;
12800	    if (ret != NULL) {
12801		xmlNodePtr tmp;
12802
12803		ret->doc = NULL;
12804		tmp = ret->children;
12805		while (tmp != NULL) {
12806		    tmp->doc = NULL;
12807		    tmp = tmp->next;
12808		}
12809	    }
12810	} else {
12811	    ret = NULL;
12812	}
12813        xmlFreeDoc(ctxt->myDoc);
12814        ctxt->myDoc = NULL;
12815    }
12816    if (sax != NULL) ctxt->sax = NULL;
12817    xmlFreeParserCtxt(ctxt);
12818
12819    return(ret);
12820}
12821
12822
12823/**
12824 * xmlParseDTD:
12825 * @ExternalID:  a NAME* containing the External ID of the DTD
12826 * @SystemID:  a NAME* containing the URL to the DTD
12827 *
12828 * Load and parse an external subset.
12829 *
12830 * Returns the resulting xmlDtdPtr or NULL in case of error.
12831 */
12832
12833xmlDtdPtr
12834xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12835    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12836}
12837#endif /* LIBXML_VALID_ENABLED */
12838
12839/************************************************************************
12840 *									*
12841 *		Front ends when parsing an Entity			*
12842 *									*
12843 ************************************************************************/
12844
12845/**
12846 * xmlParseCtxtExternalEntity:
12847 * @ctx:  the existing parsing context
12848 * @URL:  the URL for the entity to load
12849 * @ID:  the System ID for the entity to load
12850 * @lst:  the return value for the set of parsed nodes
12851 *
12852 * Parse an external general entity within an existing parsing context
12853 * An external general parsed entity is well-formed if it matches the
12854 * production labeled extParsedEnt.
12855 *
12856 * [78] extParsedEnt ::= TextDecl? content
12857 *
12858 * Returns 0 if the entity is well formed, -1 in case of args problem and
12859 *    the parser error code otherwise
12860 */
12861
12862int
12863xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12864	               const xmlChar *ID, xmlNodePtr *lst) {
12865    xmlParserCtxtPtr ctxt;
12866    xmlDocPtr newDoc;
12867    xmlNodePtr newRoot;
12868    xmlSAXHandlerPtr oldsax = NULL;
12869    int ret = 0;
12870    xmlChar start[4];
12871    xmlCharEncoding enc;
12872
12873    if (ctx == NULL) return(-1);
12874
12875    if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
12876        (ctx->depth > 1024)) {
12877	return(XML_ERR_ENTITY_LOOP);
12878    }
12879
12880    if (lst != NULL)
12881        *lst = NULL;
12882    if ((URL == NULL) && (ID == NULL))
12883	return(-1);
12884    if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
12885	return(-1);
12886
12887    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
12888    if (ctxt == NULL) {
12889	return(-1);
12890    }
12891
12892    oldsax = ctxt->sax;
12893    ctxt->sax = ctx->sax;
12894    xmlDetectSAX2(ctxt);
12895    newDoc = xmlNewDoc(BAD_CAST "1.0");
12896    if (newDoc == NULL) {
12897	xmlFreeParserCtxt(ctxt);
12898	return(-1);
12899    }
12900    newDoc->properties = XML_DOC_INTERNAL;
12901    if (ctx->myDoc->dict) {
12902	newDoc->dict = ctx->myDoc->dict;
12903	xmlDictReference(newDoc->dict);
12904    }
12905    if (ctx->myDoc != NULL) {
12906	newDoc->intSubset = ctx->myDoc->intSubset;
12907	newDoc->extSubset = ctx->myDoc->extSubset;
12908    }
12909    if (ctx->myDoc->URL != NULL) {
12910	newDoc->URL = xmlStrdup(ctx->myDoc->URL);
12911    }
12912    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12913    if (newRoot == NULL) {
12914	ctxt->sax = oldsax;
12915	xmlFreeParserCtxt(ctxt);
12916	newDoc->intSubset = NULL;
12917	newDoc->extSubset = NULL;
12918        xmlFreeDoc(newDoc);
12919	return(-1);
12920    }
12921    xmlAddChild((xmlNodePtr) newDoc, newRoot);
12922    nodePush(ctxt, newDoc->children);
12923    if (ctx->myDoc == NULL) {
12924	ctxt->myDoc = newDoc;
12925    } else {
12926	ctxt->myDoc = ctx->myDoc;
12927	newDoc->children->doc = ctx->myDoc;
12928    }
12929
12930    /*
12931     * Get the 4 first bytes and decode the charset
12932     * if enc != XML_CHAR_ENCODING_NONE
12933     * plug some encoding conversion routines.
12934     */
12935    GROW
12936    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12937	start[0] = RAW;
12938	start[1] = NXT(1);
12939	start[2] = NXT(2);
12940	start[3] = NXT(3);
12941	enc = xmlDetectCharEncoding(start, 4);
12942	if (enc != XML_CHAR_ENCODING_NONE) {
12943	    xmlSwitchEncoding(ctxt, enc);
12944	}
12945    }
12946
12947    /*
12948     * Parse a possible text declaration first
12949     */
12950    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12951	xmlParseTextDecl(ctxt);
12952	/*
12953	 * An XML-1.0 document can't reference an entity not XML-1.0
12954	 */
12955	if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
12956	    (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12957	    xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
12958	                   "Version mismatch between document and entity\n");
12959	}
12960    }
12961
12962    /*
12963     * If the user provided its own SAX callbacks then reuse the
12964     * useData callback field, otherwise the expected setup in a
12965     * DOM builder is to have userData == ctxt
12966     */
12967    if (ctx->userData == ctx)
12968        ctxt->userData = ctxt;
12969    else
12970        ctxt->userData = ctx->userData;
12971
12972    /*
12973     * Doing validity checking on chunk doesn't make sense
12974     */
12975    ctxt->instate = XML_PARSER_CONTENT;
12976    ctxt->validate = ctx->validate;
12977    ctxt->valid = ctx->valid;
12978    ctxt->loadsubset = ctx->loadsubset;
12979    ctxt->depth = ctx->depth + 1;
12980    ctxt->replaceEntities = ctx->replaceEntities;
12981    if (ctxt->validate) {
12982	ctxt->vctxt.error = ctx->vctxt.error;
12983	ctxt->vctxt.warning = ctx->vctxt.warning;
12984    } else {
12985	ctxt->vctxt.error = NULL;
12986	ctxt->vctxt.warning = NULL;
12987    }
12988    ctxt->vctxt.nodeTab = NULL;
12989    ctxt->vctxt.nodeNr = 0;
12990    ctxt->vctxt.nodeMax = 0;
12991    ctxt->vctxt.node = NULL;
12992    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12993    ctxt->dict = ctx->dict;
12994    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12995    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12996    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12997    ctxt->dictNames = ctx->dictNames;
12998    ctxt->attsDefault = ctx->attsDefault;
12999    ctxt->attsSpecial = ctx->attsSpecial;
13000    ctxt->linenumbers = ctx->linenumbers;
13001
13002    xmlParseContent(ctxt);
13003
13004    ctx->validate = ctxt->validate;
13005    ctx->valid = ctxt->valid;
13006    if ((RAW == '<') && (NXT(1) == '/')) {
13007	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13008    } else if (RAW != 0) {
13009	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13010    }
13011    if (ctxt->node != newDoc->children) {
13012	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13013    }
13014
13015    if (!ctxt->wellFormed) {
13016        if (ctxt->errNo == 0)
13017	    ret = 1;
13018	else
13019	    ret = ctxt->errNo;
13020    } else {
13021	if (lst != NULL) {
13022	    xmlNodePtr cur;
13023
13024	    /*
13025	     * Return the newly created nodeset after unlinking it from
13026	     * they pseudo parent.
13027	     */
13028	    cur = newDoc->children->children;
13029	    *lst = cur;
13030	    while (cur != NULL) {
13031		cur->parent = NULL;
13032		cur = cur->next;
13033	    }
13034            newDoc->children->children = NULL;
13035	}
13036	ret = 0;
13037    }
13038    ctxt->sax = oldsax;
13039    ctxt->dict = NULL;
13040    ctxt->attsDefault = NULL;
13041    ctxt->attsSpecial = NULL;
13042    xmlFreeParserCtxt(ctxt);
13043    newDoc->intSubset = NULL;
13044    newDoc->extSubset = NULL;
13045    xmlFreeDoc(newDoc);
13046
13047    return(ret);
13048}
13049
13050/**
13051 * xmlParseExternalEntityPrivate:
13052 * @doc:  the document the chunk pertains to
13053 * @oldctxt:  the previous parser context if available
13054 * @sax:  the SAX handler bloc (possibly NULL)
13055 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13056 * @depth:  Used for loop detection, use 0
13057 * @URL:  the URL for the entity to load
13058 * @ID:  the System ID for the entity to load
13059 * @list:  the return value for the set of parsed nodes
13060 *
13061 * Private version of xmlParseExternalEntity()
13062 *
13063 * Returns 0 if the entity is well formed, -1 in case of args problem and
13064 *    the parser error code otherwise
13065 */
13066
13067static xmlParserErrors
13068xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
13069	              xmlSAXHandlerPtr sax,
13070		      void *user_data, int depth, const xmlChar *URL,
13071		      const xmlChar *ID, xmlNodePtr *list) {
13072    xmlParserCtxtPtr ctxt;
13073    xmlDocPtr newDoc;
13074    xmlNodePtr newRoot;
13075    xmlSAXHandlerPtr oldsax = NULL;
13076    xmlParserErrors ret = XML_ERR_OK;
13077    xmlChar start[4];
13078    xmlCharEncoding enc;
13079
13080    if (((depth > 40) &&
13081	((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13082	(depth > 1024)) {
13083	return(XML_ERR_ENTITY_LOOP);
13084    }
13085
13086    if (list != NULL)
13087        *list = NULL;
13088    if ((URL == NULL) && (ID == NULL))
13089	return(XML_ERR_INTERNAL_ERROR);
13090    if (doc == NULL)
13091	return(XML_ERR_INTERNAL_ERROR);
13092
13093
13094    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
13095    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13096    ctxt->userData = ctxt;
13097    if (oldctxt != NULL) {
13098	ctxt->_private = oldctxt->_private;
13099	ctxt->loadsubset = oldctxt->loadsubset;
13100	ctxt->validate = oldctxt->validate;
13101	ctxt->external = oldctxt->external;
13102	ctxt->record_info = oldctxt->record_info;
13103	ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
13104	ctxt->node_seq.length = oldctxt->node_seq.length;
13105	ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
13106    } else {
13107	/*
13108	 * Doing validity checking on chunk without context
13109	 * doesn't make sense
13110	 */
13111	ctxt->_private = NULL;
13112	ctxt->validate = 0;
13113	ctxt->external = 2;
13114	ctxt->loadsubset = 0;
13115    }
13116    if (sax != NULL) {
13117	oldsax = ctxt->sax;
13118        ctxt->sax = sax;
13119	if (user_data != NULL)
13120	    ctxt->userData = user_data;
13121    }
13122    xmlDetectSAX2(ctxt);
13123    newDoc = xmlNewDoc(BAD_CAST "1.0");
13124    if (newDoc == NULL) {
13125	ctxt->node_seq.maximum = 0;
13126	ctxt->node_seq.length = 0;
13127	ctxt->node_seq.buffer = NULL;
13128	xmlFreeParserCtxt(ctxt);
13129	return(XML_ERR_INTERNAL_ERROR);
13130    }
13131    newDoc->properties = XML_DOC_INTERNAL;
13132    newDoc->intSubset = doc->intSubset;
13133    newDoc->extSubset = doc->extSubset;
13134    newDoc->dict = doc->dict;
13135    xmlDictReference(newDoc->dict);
13136
13137    if (doc->URL != NULL) {
13138	newDoc->URL = xmlStrdup(doc->URL);
13139    }
13140    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13141    if (newRoot == NULL) {
13142	if (sax != NULL)
13143	    ctxt->sax = oldsax;
13144	ctxt->node_seq.maximum = 0;
13145	ctxt->node_seq.length = 0;
13146	ctxt->node_seq.buffer = NULL;
13147	xmlFreeParserCtxt(ctxt);
13148	newDoc->intSubset = NULL;
13149	newDoc->extSubset = NULL;
13150        xmlFreeDoc(newDoc);
13151	return(XML_ERR_INTERNAL_ERROR);
13152    }
13153    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13154    nodePush(ctxt, newDoc->children);
13155    ctxt->myDoc = doc;
13156    newRoot->doc = doc;
13157
13158    /*
13159     * Get the 4 first bytes and decode the charset
13160     * if enc != XML_CHAR_ENCODING_NONE
13161     * plug some encoding conversion routines.
13162     */
13163    GROW;
13164    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
13165	start[0] = RAW;
13166	start[1] = NXT(1);
13167	start[2] = NXT(2);
13168	start[3] = NXT(3);
13169	enc = xmlDetectCharEncoding(start, 4);
13170	if (enc != XML_CHAR_ENCODING_NONE) {
13171	    xmlSwitchEncoding(ctxt, enc);
13172	}
13173    }
13174
13175    /*
13176     * Parse a possible text declaration first
13177     */
13178    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
13179	xmlParseTextDecl(ctxt);
13180    }
13181
13182    ctxt->instate = XML_PARSER_CONTENT;
13183    ctxt->depth = depth;
13184
13185    xmlParseContent(ctxt);
13186
13187    if ((RAW == '<') && (NXT(1) == '/')) {
13188	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13189    } else if (RAW != 0) {
13190	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13191    }
13192    if (ctxt->node != newDoc->children) {
13193	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13194    }
13195
13196    if (!ctxt->wellFormed) {
13197        if (ctxt->errNo == 0)
13198	    ret = XML_ERR_INTERNAL_ERROR;
13199	else
13200	    ret = (xmlParserErrors)ctxt->errNo;
13201    } else {
13202	if (list != NULL) {
13203	    xmlNodePtr cur;
13204
13205	    /*
13206	     * Return the newly created nodeset after unlinking it from
13207	     * they pseudo parent.
13208	     */
13209	    cur = newDoc->children->children;
13210	    *list = cur;
13211	    while (cur != NULL) {
13212		cur->parent = NULL;
13213		cur = cur->next;
13214	    }
13215            newDoc->children->children = NULL;
13216	}
13217	ret = XML_ERR_OK;
13218    }
13219
13220    /*
13221     * Record in the parent context the number of entities replacement
13222     * done when parsing that reference.
13223     */
13224    if (oldctxt != NULL)
13225        oldctxt->nbentities += ctxt->nbentities;
13226
13227    /*
13228     * Also record the size of the entity parsed
13229     */
13230    if (ctxt->input != NULL) {
13231	oldctxt->sizeentities += ctxt->input->consumed;
13232	oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
13233    }
13234    /*
13235     * And record the last error if any
13236     */
13237    if (ctxt->lastError.code != XML_ERR_OK)
13238        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13239
13240    if (sax != NULL)
13241	ctxt->sax = oldsax;
13242    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
13243    oldctxt->node_seq.length = ctxt->node_seq.length;
13244    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
13245    ctxt->node_seq.maximum = 0;
13246    ctxt->node_seq.length = 0;
13247    ctxt->node_seq.buffer = NULL;
13248    xmlFreeParserCtxt(ctxt);
13249    newDoc->intSubset = NULL;
13250    newDoc->extSubset = NULL;
13251    xmlFreeDoc(newDoc);
13252
13253    return(ret);
13254}
13255
13256#ifdef LIBXML_SAX1_ENABLED
13257/**
13258 * xmlParseExternalEntity:
13259 * @doc:  the document the chunk pertains to
13260 * @sax:  the SAX handler bloc (possibly NULL)
13261 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13262 * @depth:  Used for loop detection, use 0
13263 * @URL:  the URL for the entity to load
13264 * @ID:  the System ID for the entity to load
13265 * @lst:  the return value for the set of parsed nodes
13266 *
13267 * Parse an external general entity
13268 * An external general parsed entity is well-formed if it matches the
13269 * production labeled extParsedEnt.
13270 *
13271 * [78] extParsedEnt ::= TextDecl? content
13272 *
13273 * Returns 0 if the entity is well formed, -1 in case of args problem and
13274 *    the parser error code otherwise
13275 */
13276
13277int
13278xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
13279	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
13280    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
13281		                       ID, lst));
13282}
13283
13284/**
13285 * xmlParseBalancedChunkMemory:
13286 * @doc:  the document the chunk pertains to
13287 * @sax:  the SAX handler bloc (possibly NULL)
13288 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13289 * @depth:  Used for loop detection, use 0
13290 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13291 * @lst:  the return value for the set of parsed nodes
13292 *
13293 * Parse a well-balanced chunk of an XML document
13294 * called by the parser
13295 * The allowed sequence for the Well Balanced Chunk is the one defined by
13296 * the content production in the XML grammar:
13297 *
13298 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13299 *
13300 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13301 *    the parser error code otherwise
13302 */
13303
13304int
13305xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13306     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
13307    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
13308                                                depth, string, lst, 0 );
13309}
13310#endif /* LIBXML_SAX1_ENABLED */
13311
13312/**
13313 * xmlParseBalancedChunkMemoryInternal:
13314 * @oldctxt:  the existing parsing context
13315 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13316 * @user_data:  the user data field for the parser context
13317 * @lst:  the return value for the set of parsed nodes
13318 *
13319 *
13320 * Parse a well-balanced chunk of an XML document
13321 * called by the parser
13322 * The allowed sequence for the Well Balanced Chunk is the one defined by
13323 * the content production in the XML grammar:
13324 *
13325 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13326 *
13327 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13328 * error code otherwise
13329 *
13330 * In case recover is set to 1, the nodelist will not be empty even if
13331 * the parsed chunk is not well balanced.
13332 */
13333static xmlParserErrors
13334xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13335	const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13336    xmlParserCtxtPtr ctxt;
13337    xmlDocPtr newDoc = NULL;
13338    xmlNodePtr newRoot;
13339    xmlSAXHandlerPtr oldsax = NULL;
13340    xmlNodePtr content = NULL;
13341    xmlNodePtr last = NULL;
13342    int size;
13343    xmlParserErrors ret = XML_ERR_OK;
13344#ifdef SAX2
13345    int i;
13346#endif
13347
13348    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13349        (oldctxt->depth >  1024)) {
13350	return(XML_ERR_ENTITY_LOOP);
13351    }
13352
13353
13354    if (lst != NULL)
13355        *lst = NULL;
13356    if (string == NULL)
13357        return(XML_ERR_INTERNAL_ERROR);
13358
13359    size = xmlStrlen(string);
13360
13361    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13362    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13363    if (user_data != NULL)
13364	ctxt->userData = user_data;
13365    else
13366	ctxt->userData = ctxt;
13367    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13368    ctxt->dict = oldctxt->dict;
13369    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13370    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13371    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13372
13373#ifdef SAX2
13374    /* propagate namespaces down the entity */
13375    for (i = 0;i < oldctxt->nsNr;i += 2) {
13376        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
13377    }
13378#endif
13379
13380    oldsax = ctxt->sax;
13381    ctxt->sax = oldctxt->sax;
13382    xmlDetectSAX2(ctxt);
13383    ctxt->replaceEntities = oldctxt->replaceEntities;
13384    ctxt->options = oldctxt->options;
13385
13386    ctxt->_private = oldctxt->_private;
13387    if (oldctxt->myDoc == NULL) {
13388	newDoc = xmlNewDoc(BAD_CAST "1.0");
13389	if (newDoc == NULL) {
13390	    ctxt->sax = oldsax;
13391	    ctxt->dict = NULL;
13392	    xmlFreeParserCtxt(ctxt);
13393	    return(XML_ERR_INTERNAL_ERROR);
13394	}
13395	newDoc->properties = XML_DOC_INTERNAL;
13396	newDoc->dict = ctxt->dict;
13397	xmlDictReference(newDoc->dict);
13398	ctxt->myDoc = newDoc;
13399    } else {
13400	ctxt->myDoc = oldctxt->myDoc;
13401        content = ctxt->myDoc->children;
13402	last = ctxt->myDoc->last;
13403    }
13404    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13405    if (newRoot == NULL) {
13406	ctxt->sax = oldsax;
13407	ctxt->dict = NULL;
13408	xmlFreeParserCtxt(ctxt);
13409	if (newDoc != NULL) {
13410	    xmlFreeDoc(newDoc);
13411	}
13412	return(XML_ERR_INTERNAL_ERROR);
13413    }
13414    ctxt->myDoc->children = NULL;
13415    ctxt->myDoc->last = NULL;
13416    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13417    nodePush(ctxt, ctxt->myDoc->children);
13418    ctxt->instate = XML_PARSER_CONTENT;
13419    ctxt->depth = oldctxt->depth + 1;
13420
13421    ctxt->validate = 0;
13422    ctxt->loadsubset = oldctxt->loadsubset;
13423    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13424	/*
13425	 * ID/IDREF registration will be done in xmlValidateElement below
13426	 */
13427	ctxt->loadsubset |= XML_SKIP_IDS;
13428    }
13429    ctxt->dictNames = oldctxt->dictNames;
13430    ctxt->attsDefault = oldctxt->attsDefault;
13431    ctxt->attsSpecial = oldctxt->attsSpecial;
13432
13433    xmlParseContent(ctxt);
13434    if ((RAW == '<') && (NXT(1) == '/')) {
13435	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13436    } else if (RAW != 0) {
13437	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13438    }
13439    if (ctxt->node != ctxt->myDoc->children) {
13440	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13441    }
13442
13443    if (!ctxt->wellFormed) {
13444        if (ctxt->errNo == 0)
13445	    ret = XML_ERR_INTERNAL_ERROR;
13446	else
13447	    ret = (xmlParserErrors)ctxt->errNo;
13448    } else {
13449      ret = XML_ERR_OK;
13450    }
13451
13452    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13453	xmlNodePtr cur;
13454
13455	/*
13456	 * Return the newly created nodeset after unlinking it from
13457	 * they pseudo parent.
13458	 */
13459	cur = ctxt->myDoc->children->children;
13460	*lst = cur;
13461	while (cur != NULL) {
13462#ifdef LIBXML_VALID_ENABLED
13463	    if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13464		(oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13465		(cur->type == XML_ELEMENT_NODE)) {
13466		oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13467			oldctxt->myDoc, cur);
13468	    }
13469#endif /* LIBXML_VALID_ENABLED */
13470	    cur->parent = NULL;
13471	    cur = cur->next;
13472	}
13473	ctxt->myDoc->children->children = NULL;
13474    }
13475    if (ctxt->myDoc != NULL) {
13476	xmlFreeNode(ctxt->myDoc->children);
13477        ctxt->myDoc->children = content;
13478        ctxt->myDoc->last = last;
13479    }
13480
13481    /*
13482     * Record in the parent context the number of entities replacement
13483     * done when parsing that reference.
13484     */
13485    if (oldctxt != NULL)
13486        oldctxt->nbentities += ctxt->nbentities;
13487
13488    /*
13489     * Also record the last error if any
13490     */
13491    if (ctxt->lastError.code != XML_ERR_OK)
13492        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13493
13494    ctxt->sax = oldsax;
13495    ctxt->dict = NULL;
13496    ctxt->attsDefault = NULL;
13497    ctxt->attsSpecial = NULL;
13498    xmlFreeParserCtxt(ctxt);
13499    if (newDoc != NULL) {
13500	xmlFreeDoc(newDoc);
13501    }
13502
13503    return(ret);
13504}
13505
13506/**
13507 * xmlParseInNodeContext:
13508 * @node:  the context node
13509 * @data:  the input string
13510 * @datalen:  the input string length in bytes
13511 * @options:  a combination of xmlParserOption
13512 * @lst:  the return value for the set of parsed nodes
13513 *
13514 * Parse a well-balanced chunk of an XML document
13515 * within the context (DTD, namespaces, etc ...) of the given node.
13516 *
13517 * The allowed sequence for the data is a Well Balanced Chunk defined by
13518 * the content production in the XML grammar:
13519 *
13520 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13521 *
13522 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13523 * error code otherwise
13524 */
13525xmlParserErrors
13526xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13527                      int options, xmlNodePtr *lst) {
13528#ifdef SAX2
13529    xmlParserCtxtPtr ctxt;
13530    xmlDocPtr doc = NULL;
13531    xmlNodePtr fake, cur;
13532    int nsnr = 0;
13533
13534    xmlParserErrors ret = XML_ERR_OK;
13535
13536    /*
13537     * check all input parameters, grab the document
13538     */
13539    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13540        return(XML_ERR_INTERNAL_ERROR);
13541    switch (node->type) {
13542        case XML_ELEMENT_NODE:
13543        case XML_ATTRIBUTE_NODE:
13544        case XML_TEXT_NODE:
13545        case XML_CDATA_SECTION_NODE:
13546        case XML_ENTITY_REF_NODE:
13547        case XML_PI_NODE:
13548        case XML_COMMENT_NODE:
13549        case XML_DOCUMENT_NODE:
13550        case XML_HTML_DOCUMENT_NODE:
13551	    break;
13552	default:
13553	    return(XML_ERR_INTERNAL_ERROR);
13554
13555    }
13556    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13557           (node->type != XML_DOCUMENT_NODE) &&
13558	   (node->type != XML_HTML_DOCUMENT_NODE))
13559	node = node->parent;
13560    if (node == NULL)
13561	return(XML_ERR_INTERNAL_ERROR);
13562    if (node->type == XML_ELEMENT_NODE)
13563	doc = node->doc;
13564    else
13565        doc = (xmlDocPtr) node;
13566    if (doc == NULL)
13567	return(XML_ERR_INTERNAL_ERROR);
13568
13569    /*
13570     * allocate a context and set-up everything not related to the
13571     * node position in the tree
13572     */
13573    if (doc->type == XML_DOCUMENT_NODE)
13574	ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13575#ifdef LIBXML_HTML_ENABLED
13576    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13577	ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13578        /*
13579         * When parsing in context, it makes no sense to add implied
13580         * elements like html/body/etc...
13581         */
13582        options |= HTML_PARSE_NOIMPLIED;
13583    }
13584#endif
13585    else
13586        return(XML_ERR_INTERNAL_ERROR);
13587
13588    if (ctxt == NULL)
13589        return(XML_ERR_NO_MEMORY);
13590
13591    /*
13592     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13593     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13594     * we must wait until the last moment to free the original one.
13595     */
13596    if (doc->dict != NULL) {
13597        if (ctxt->dict != NULL)
13598	    xmlDictFree(ctxt->dict);
13599	ctxt->dict = doc->dict;
13600    } else
13601        options |= XML_PARSE_NODICT;
13602
13603    if (doc->encoding != NULL) {
13604        xmlCharEncodingHandlerPtr hdlr;
13605
13606        if (ctxt->encoding != NULL)
13607	    xmlFree((xmlChar *) ctxt->encoding);
13608        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13609
13610        hdlr = xmlFindCharEncodingHandler(doc->encoding);
13611        if (hdlr != NULL) {
13612            xmlSwitchToEncoding(ctxt, hdlr);
13613	} else {
13614            return(XML_ERR_UNSUPPORTED_ENCODING);
13615        }
13616    }
13617
13618    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13619    xmlDetectSAX2(ctxt);
13620    ctxt->myDoc = doc;
13621
13622    fake = xmlNewComment(NULL);
13623    if (fake == NULL) {
13624        xmlFreeParserCtxt(ctxt);
13625	return(XML_ERR_NO_MEMORY);
13626    }
13627    xmlAddChild(node, fake);
13628
13629    if (node->type == XML_ELEMENT_NODE) {
13630	nodePush(ctxt, node);
13631	/*
13632	 * initialize the SAX2 namespaces stack
13633	 */
13634	cur = node;
13635	while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13636	    xmlNsPtr ns = cur->nsDef;
13637	    const xmlChar *iprefix, *ihref;
13638
13639	    while (ns != NULL) {
13640		if (ctxt->dict) {
13641		    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13642		    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13643		} else {
13644		    iprefix = ns->prefix;
13645		    ihref = ns->href;
13646		}
13647
13648	        if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13649		    nsPush(ctxt, iprefix, ihref);
13650		    nsnr++;
13651		}
13652		ns = ns->next;
13653	    }
13654	    cur = cur->parent;
13655	}
13656	ctxt->instate = XML_PARSER_CONTENT;
13657    }
13658
13659    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13660	/*
13661	 * ID/IDREF registration will be done in xmlValidateElement below
13662	 */
13663	ctxt->loadsubset |= XML_SKIP_IDS;
13664    }
13665
13666#ifdef LIBXML_HTML_ENABLED
13667    if (doc->type == XML_HTML_DOCUMENT_NODE)
13668        __htmlParseContent(ctxt);
13669    else
13670#endif
13671	xmlParseContent(ctxt);
13672
13673    nsPop(ctxt, nsnr);
13674    if ((RAW == '<') && (NXT(1) == '/')) {
13675	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13676    } else if (RAW != 0) {
13677	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13678    }
13679    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13680	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13681	ctxt->wellFormed = 0;
13682    }
13683
13684    if (!ctxt->wellFormed) {
13685        if (ctxt->errNo == 0)
13686	    ret = XML_ERR_INTERNAL_ERROR;
13687	else
13688	    ret = (xmlParserErrors)ctxt->errNo;
13689    } else {
13690        ret = XML_ERR_OK;
13691    }
13692
13693    /*
13694     * Return the newly created nodeset after unlinking it from
13695     * the pseudo sibling.
13696     */
13697
13698    cur = fake->next;
13699    fake->next = NULL;
13700    node->last = fake;
13701
13702    if (cur != NULL) {
13703	cur->prev = NULL;
13704    }
13705
13706    *lst = cur;
13707
13708    while (cur != NULL) {
13709	cur->parent = NULL;
13710	cur = cur->next;
13711    }
13712
13713    xmlUnlinkNode(fake);
13714    xmlFreeNode(fake);
13715
13716
13717    if (ret != XML_ERR_OK) {
13718        xmlFreeNodeList(*lst);
13719	*lst = NULL;
13720    }
13721
13722    if (doc->dict != NULL)
13723        ctxt->dict = NULL;
13724    xmlFreeParserCtxt(ctxt);
13725
13726    return(ret);
13727#else /* !SAX2 */
13728    return(XML_ERR_INTERNAL_ERROR);
13729#endif
13730}
13731
13732#ifdef LIBXML_SAX1_ENABLED
13733/**
13734 * xmlParseBalancedChunkMemoryRecover:
13735 * @doc:  the document the chunk pertains to
13736 * @sax:  the SAX handler bloc (possibly NULL)
13737 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13738 * @depth:  Used for loop detection, use 0
13739 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13740 * @lst:  the return value for the set of parsed nodes
13741 * @recover: return nodes even if the data is broken (use 0)
13742 *
13743 *
13744 * Parse a well-balanced chunk of an XML document
13745 * called by the parser
13746 * The allowed sequence for the Well Balanced Chunk is the one defined by
13747 * the content production in the XML grammar:
13748 *
13749 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13750 *
13751 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13752 *    the parser error code otherwise
13753 *
13754 * In case recover is set to 1, the nodelist will not be empty even if
13755 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13756 * some extent.
13757 */
13758int
13759xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13760     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13761     int recover) {
13762    xmlParserCtxtPtr ctxt;
13763    xmlDocPtr newDoc;
13764    xmlSAXHandlerPtr oldsax = NULL;
13765    xmlNodePtr content, newRoot;
13766    int size;
13767    int ret = 0;
13768
13769    if (depth > 40) {
13770	return(XML_ERR_ENTITY_LOOP);
13771    }
13772
13773
13774    if (lst != NULL)
13775        *lst = NULL;
13776    if (string == NULL)
13777        return(-1);
13778
13779    size = xmlStrlen(string);
13780
13781    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13782    if (ctxt == NULL) return(-1);
13783    ctxt->userData = ctxt;
13784    if (sax != NULL) {
13785	oldsax = ctxt->sax;
13786        ctxt->sax = sax;
13787	if (user_data != NULL)
13788	    ctxt->userData = user_data;
13789    }
13790    newDoc = xmlNewDoc(BAD_CAST "1.0");
13791    if (newDoc == NULL) {
13792	xmlFreeParserCtxt(ctxt);
13793	return(-1);
13794    }
13795    newDoc->properties = XML_DOC_INTERNAL;
13796    if ((doc != NULL) && (doc->dict != NULL)) {
13797        xmlDictFree(ctxt->dict);
13798	ctxt->dict = doc->dict;
13799	xmlDictReference(ctxt->dict);
13800	ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13801	ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13802	ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13803	ctxt->dictNames = 1;
13804    } else {
13805	xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13806    }
13807    if (doc != NULL) {
13808	newDoc->intSubset = doc->intSubset;
13809	newDoc->extSubset = doc->extSubset;
13810    }
13811    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13812    if (newRoot == NULL) {
13813	if (sax != NULL)
13814	    ctxt->sax = oldsax;
13815	xmlFreeParserCtxt(ctxt);
13816	newDoc->intSubset = NULL;
13817	newDoc->extSubset = NULL;
13818        xmlFreeDoc(newDoc);
13819	return(-1);
13820    }
13821    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13822    nodePush(ctxt, newRoot);
13823    if (doc == NULL) {
13824	ctxt->myDoc = newDoc;
13825    } else {
13826	ctxt->myDoc = newDoc;
13827	newDoc->children->doc = doc;
13828	/* Ensure that doc has XML spec namespace */
13829	xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13830	newDoc->oldNs = doc->oldNs;
13831    }
13832    ctxt->instate = XML_PARSER_CONTENT;
13833    ctxt->depth = depth;
13834
13835    /*
13836     * Doing validity checking on chunk doesn't make sense
13837     */
13838    ctxt->validate = 0;
13839    ctxt->loadsubset = 0;
13840    xmlDetectSAX2(ctxt);
13841
13842    if ( doc != NULL ){
13843        content = doc->children;
13844        doc->children = NULL;
13845        xmlParseContent(ctxt);
13846        doc->children = content;
13847    }
13848    else {
13849        xmlParseContent(ctxt);
13850    }
13851    if ((RAW == '<') && (NXT(1) == '/')) {
13852	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13853    } else if (RAW != 0) {
13854	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13855    }
13856    if (ctxt->node != newDoc->children) {
13857	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13858    }
13859
13860    if (!ctxt->wellFormed) {
13861        if (ctxt->errNo == 0)
13862	    ret = 1;
13863	else
13864	    ret = ctxt->errNo;
13865    } else {
13866      ret = 0;
13867    }
13868
13869    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13870	xmlNodePtr cur;
13871
13872	/*
13873	 * Return the newly created nodeset after unlinking it from
13874	 * they pseudo parent.
13875	 */
13876	cur = newDoc->children->children;
13877	*lst = cur;
13878	while (cur != NULL) {
13879	    xmlSetTreeDoc(cur, doc);
13880	    cur->parent = NULL;
13881	    cur = cur->next;
13882	}
13883	newDoc->children->children = NULL;
13884    }
13885
13886    if (sax != NULL)
13887	ctxt->sax = oldsax;
13888    xmlFreeParserCtxt(ctxt);
13889    newDoc->intSubset = NULL;
13890    newDoc->extSubset = NULL;
13891    newDoc->oldNs = NULL;
13892    xmlFreeDoc(newDoc);
13893
13894    return(ret);
13895}
13896
13897/**
13898 * xmlSAXParseEntity:
13899 * @sax:  the SAX handler block
13900 * @filename:  the filename
13901 *
13902 * parse an XML external entity out of context and build a tree.
13903 * It use the given SAX function block to handle the parsing callback.
13904 * If sax is NULL, fallback to the default DOM tree building routines.
13905 *
13906 * [78] extParsedEnt ::= TextDecl? content
13907 *
13908 * This correspond to a "Well Balanced" chunk
13909 *
13910 * Returns the resulting document tree
13911 */
13912
13913xmlDocPtr
13914xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13915    xmlDocPtr ret;
13916    xmlParserCtxtPtr ctxt;
13917
13918    ctxt = xmlCreateFileParserCtxt(filename);
13919    if (ctxt == NULL) {
13920	return(NULL);
13921    }
13922    if (sax != NULL) {
13923	if (ctxt->sax != NULL)
13924	    xmlFree(ctxt->sax);
13925        ctxt->sax = sax;
13926        ctxt->userData = NULL;
13927    }
13928
13929    xmlParseExtParsedEnt(ctxt);
13930
13931    if (ctxt->wellFormed)
13932	ret = ctxt->myDoc;
13933    else {
13934        ret = NULL;
13935        xmlFreeDoc(ctxt->myDoc);
13936        ctxt->myDoc = NULL;
13937    }
13938    if (sax != NULL)
13939        ctxt->sax = NULL;
13940    xmlFreeParserCtxt(ctxt);
13941
13942    return(ret);
13943}
13944
13945/**
13946 * xmlParseEntity:
13947 * @filename:  the filename
13948 *
13949 * parse an XML external entity out of context and build a tree.
13950 *
13951 * [78] extParsedEnt ::= TextDecl? content
13952 *
13953 * This correspond to a "Well Balanced" chunk
13954 *
13955 * Returns the resulting document tree
13956 */
13957
13958xmlDocPtr
13959xmlParseEntity(const char *filename) {
13960    return(xmlSAXParseEntity(NULL, filename));
13961}
13962#endif /* LIBXML_SAX1_ENABLED */
13963
13964/**
13965 * xmlCreateEntityParserCtxtInternal:
13966 * @URL:  the entity URL
13967 * @ID:  the entity PUBLIC ID
13968 * @base:  a possible base for the target URI
13969 * @pctx:  parser context used to set options on new context
13970 *
13971 * Create a parser context for an external entity
13972 * Automatic support for ZLIB/Compress compressed document is provided
13973 * by default if found at compile-time.
13974 *
13975 * Returns the new parser context or NULL
13976 */
13977static xmlParserCtxtPtr
13978xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
13979	                  const xmlChar *base, xmlParserCtxtPtr pctx) {
13980    xmlParserCtxtPtr ctxt;
13981    xmlParserInputPtr inputStream;
13982    char *directory = NULL;
13983    xmlChar *uri;
13984
13985    ctxt = xmlNewParserCtxt();
13986    if (ctxt == NULL) {
13987	return(NULL);
13988    }
13989
13990    if (pctx != NULL) {
13991        ctxt->options = pctx->options;
13992        ctxt->_private = pctx->_private;
13993    }
13994
13995    uri = xmlBuildURI(URL, base);
13996
13997    if (uri == NULL) {
13998	inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13999	if (inputStream == NULL) {
14000	    xmlFreeParserCtxt(ctxt);
14001	    return(NULL);
14002	}
14003
14004	inputPush(ctxt, inputStream);
14005
14006	if ((ctxt->directory == NULL) && (directory == NULL))
14007	    directory = xmlParserGetDirectory((char *)URL);
14008	if ((ctxt->directory == NULL) && (directory != NULL))
14009	    ctxt->directory = directory;
14010    } else {
14011	inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
14012	if (inputStream == NULL) {
14013	    xmlFree(uri);
14014	    xmlFreeParserCtxt(ctxt);
14015	    return(NULL);
14016	}
14017
14018	inputPush(ctxt, inputStream);
14019
14020	if ((ctxt->directory == NULL) && (directory == NULL))
14021	    directory = xmlParserGetDirectory((char *)uri);
14022	if ((ctxt->directory == NULL) && (directory != NULL))
14023	    ctxt->directory = directory;
14024	xmlFree(uri);
14025    }
14026    return(ctxt);
14027}
14028
14029/**
14030 * xmlCreateEntityParserCtxt:
14031 * @URL:  the entity URL
14032 * @ID:  the entity PUBLIC ID
14033 * @base:  a possible base for the target URI
14034 *
14035 * Create a parser context for an external entity
14036 * Automatic support for ZLIB/Compress compressed document is provided
14037 * by default if found at compile-time.
14038 *
14039 * Returns the new parser context or NULL
14040 */
14041xmlParserCtxtPtr
14042xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
14043	                  const xmlChar *base) {
14044    return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
14045
14046}
14047
14048/************************************************************************
14049 *									*
14050 *		Front ends when parsing from a file			*
14051 *									*
14052 ************************************************************************/
14053
14054/**
14055 * xmlCreateURLParserCtxt:
14056 * @filename:  the filename or URL
14057 * @options:  a combination of xmlParserOption
14058 *
14059 * Create a parser context for a file or URL content.
14060 * Automatic support for ZLIB/Compress compressed document is provided
14061 * by default if found at compile-time and for file accesses
14062 *
14063 * Returns the new parser context or NULL
14064 */
14065xmlParserCtxtPtr
14066xmlCreateURLParserCtxt(const char *filename, int options)
14067{
14068    xmlParserCtxtPtr ctxt;
14069    xmlParserInputPtr inputStream;
14070    char *directory = NULL;
14071
14072    ctxt = xmlNewParserCtxt();
14073    if (ctxt == NULL) {
14074	xmlErrMemory(NULL, "cannot allocate parser context");
14075	return(NULL);
14076    }
14077
14078    if (options)
14079	xmlCtxtUseOptionsInternal(ctxt, options, NULL);
14080    ctxt->linenumbers = 1;
14081
14082    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
14083    if (inputStream == NULL) {
14084	xmlFreeParserCtxt(ctxt);
14085	return(NULL);
14086    }
14087
14088    inputPush(ctxt, inputStream);
14089    if ((ctxt->directory == NULL) && (directory == NULL))
14090        directory = xmlParserGetDirectory(filename);
14091    if ((ctxt->directory == NULL) && (directory != NULL))
14092        ctxt->directory = directory;
14093
14094    return(ctxt);
14095}
14096
14097/**
14098 * xmlCreateFileParserCtxt:
14099 * @filename:  the filename
14100 *
14101 * Create a parser context for a file content.
14102 * Automatic support for ZLIB/Compress compressed document is provided
14103 * by default if found at compile-time.
14104 *
14105 * Returns the new parser context or NULL
14106 */
14107xmlParserCtxtPtr
14108xmlCreateFileParserCtxt(const char *filename)
14109{
14110    return(xmlCreateURLParserCtxt(filename, 0));
14111}
14112
14113#ifdef LIBXML_SAX1_ENABLED
14114/**
14115 * xmlSAXParseFileWithData:
14116 * @sax:  the SAX handler block
14117 * @filename:  the filename
14118 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14119 *             documents
14120 * @data:  the userdata
14121 *
14122 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14123 * compressed document is provided by default if found at compile-time.
14124 * It use the given SAX function block to handle the parsing callback.
14125 * If sax is NULL, fallback to the default DOM tree building routines.
14126 *
14127 * User data (void *) is stored within the parser context in the
14128 * context's _private member, so it is available nearly everywhere in libxml
14129 *
14130 * Returns the resulting document tree
14131 */
14132
14133xmlDocPtr
14134xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
14135                        int recovery, void *data) {
14136    xmlDocPtr ret;
14137    xmlParserCtxtPtr ctxt;
14138
14139    xmlInitParser();
14140
14141    ctxt = xmlCreateFileParserCtxt(filename);
14142    if (ctxt == NULL) {
14143	return(NULL);
14144    }
14145    if (sax != NULL) {
14146	if (ctxt->sax != NULL)
14147	    xmlFree(ctxt->sax);
14148        ctxt->sax = sax;
14149    }
14150    xmlDetectSAX2(ctxt);
14151    if (data!=NULL) {
14152	ctxt->_private = data;
14153    }
14154
14155    if (ctxt->directory == NULL)
14156        ctxt->directory = xmlParserGetDirectory(filename);
14157
14158    ctxt->recovery = recovery;
14159
14160    xmlParseDocument(ctxt);
14161
14162    if ((ctxt->wellFormed) || recovery) {
14163        ret = ctxt->myDoc;
14164	if (ret != NULL) {
14165	    if (ctxt->input->buf->compressed > 0)
14166		ret->compression = 9;
14167	    else
14168		ret->compression = ctxt->input->buf->compressed;
14169	}
14170    }
14171    else {
14172       ret = NULL;
14173       xmlFreeDoc(ctxt->myDoc);
14174       ctxt->myDoc = NULL;
14175    }
14176    if (sax != NULL)
14177        ctxt->sax = NULL;
14178    xmlFreeParserCtxt(ctxt);
14179
14180    return(ret);
14181}
14182
14183/**
14184 * xmlSAXParseFile:
14185 * @sax:  the SAX handler block
14186 * @filename:  the filename
14187 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14188 *             documents
14189 *
14190 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14191 * compressed document is provided by default if found at compile-time.
14192 * It use the given SAX function block to handle the parsing callback.
14193 * If sax is NULL, fallback to the default DOM tree building routines.
14194 *
14195 * Returns the resulting document tree
14196 */
14197
14198xmlDocPtr
14199xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
14200                          int recovery) {
14201    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
14202}
14203
14204/**
14205 * xmlRecoverDoc:
14206 * @cur:  a pointer to an array of xmlChar
14207 *
14208 * parse an XML in-memory document and build a tree.
14209 * In the case the document is not Well Formed, a attempt to build a
14210 * tree is tried anyway
14211 *
14212 * Returns the resulting document tree or NULL in case of failure
14213 */
14214
14215xmlDocPtr
14216xmlRecoverDoc(const xmlChar *cur) {
14217    return(xmlSAXParseDoc(NULL, cur, 1));
14218}
14219
14220/**
14221 * xmlParseFile:
14222 * @filename:  the filename
14223 *
14224 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14225 * compressed document is provided by default if found at compile-time.
14226 *
14227 * Returns the resulting document tree if the file was wellformed,
14228 * NULL otherwise.
14229 */
14230
14231xmlDocPtr
14232xmlParseFile(const char *filename) {
14233    return(xmlSAXParseFile(NULL, filename, 0));
14234}
14235
14236/**
14237 * xmlRecoverFile:
14238 * @filename:  the filename
14239 *
14240 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14241 * compressed document is provided by default if found at compile-time.
14242 * In the case the document is not Well Formed, it attempts to build
14243 * a tree anyway
14244 *
14245 * Returns the resulting document tree or NULL in case of failure
14246 */
14247
14248xmlDocPtr
14249xmlRecoverFile(const char *filename) {
14250    return(xmlSAXParseFile(NULL, filename, 1));
14251}
14252
14253
14254/**
14255 * xmlSetupParserForBuffer:
14256 * @ctxt:  an XML parser context
14257 * @buffer:  a xmlChar * buffer
14258 * @filename:  a file name
14259 *
14260 * Setup the parser context to parse a new buffer; Clears any prior
14261 * contents from the parser context. The buffer parameter must not be
14262 * NULL, but the filename parameter can be
14263 */
14264void
14265xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
14266                             const char* filename)
14267{
14268    xmlParserInputPtr input;
14269
14270    if ((ctxt == NULL) || (buffer == NULL))
14271        return;
14272
14273    input = xmlNewInputStream(ctxt);
14274    if (input == NULL) {
14275        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
14276        xmlClearParserCtxt(ctxt);
14277        return;
14278    }
14279
14280    xmlClearParserCtxt(ctxt);
14281    if (filename != NULL)
14282        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14283    input->base = buffer;
14284    input->cur = buffer;
14285    input->end = &buffer[xmlStrlen(buffer)];
14286    inputPush(ctxt, input);
14287}
14288
14289/**
14290 * xmlSAXUserParseFile:
14291 * @sax:  a SAX handler
14292 * @user_data:  The user data returned on SAX callbacks
14293 * @filename:  a file name
14294 *
14295 * parse an XML file and call the given SAX handler routines.
14296 * Automatic support for ZLIB/Compress compressed document is provided
14297 *
14298 * Returns 0 in case of success or a error number otherwise
14299 */
14300int
14301xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14302                    const char *filename) {
14303    int ret = 0;
14304    xmlParserCtxtPtr ctxt;
14305
14306    ctxt = xmlCreateFileParserCtxt(filename);
14307    if (ctxt == NULL) return -1;
14308    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14309	xmlFree(ctxt->sax);
14310    ctxt->sax = sax;
14311    xmlDetectSAX2(ctxt);
14312
14313    if (user_data != NULL)
14314	ctxt->userData = user_data;
14315
14316    xmlParseDocument(ctxt);
14317
14318    if (ctxt->wellFormed)
14319	ret = 0;
14320    else {
14321        if (ctxt->errNo != 0)
14322	    ret = ctxt->errNo;
14323	else
14324	    ret = -1;
14325    }
14326    if (sax != NULL)
14327	ctxt->sax = NULL;
14328    if (ctxt->myDoc != NULL) {
14329        xmlFreeDoc(ctxt->myDoc);
14330	ctxt->myDoc = NULL;
14331    }
14332    xmlFreeParserCtxt(ctxt);
14333
14334    return ret;
14335}
14336#endif /* LIBXML_SAX1_ENABLED */
14337
14338/************************************************************************
14339 *									*
14340 *		Front ends when parsing from memory			*
14341 *									*
14342 ************************************************************************/
14343
14344/**
14345 * xmlCreateMemoryParserCtxt:
14346 * @buffer:  a pointer to a char array
14347 * @size:  the size of the array
14348 *
14349 * Create a parser context for an XML in-memory document.
14350 *
14351 * Returns the new parser context or NULL
14352 */
14353xmlParserCtxtPtr
14354xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14355    xmlParserCtxtPtr ctxt;
14356    xmlParserInputPtr input;
14357    xmlParserInputBufferPtr buf;
14358
14359    if (buffer == NULL)
14360	return(NULL);
14361    if (size <= 0)
14362	return(NULL);
14363
14364    ctxt = xmlNewParserCtxt();
14365    if (ctxt == NULL)
14366	return(NULL);
14367
14368    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
14369    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14370    if (buf == NULL) {
14371	xmlFreeParserCtxt(ctxt);
14372	return(NULL);
14373    }
14374
14375    input = xmlNewInputStream(ctxt);
14376    if (input == NULL) {
14377	xmlFreeParserInputBuffer(buf);
14378	xmlFreeParserCtxt(ctxt);
14379	return(NULL);
14380    }
14381
14382    input->filename = NULL;
14383    input->buf = buf;
14384    xmlBufResetInput(input->buf->buffer, input);
14385
14386    inputPush(ctxt, input);
14387    return(ctxt);
14388}
14389
14390#ifdef LIBXML_SAX1_ENABLED
14391/**
14392 * xmlSAXParseMemoryWithData:
14393 * @sax:  the SAX handler block
14394 * @buffer:  an pointer to a char array
14395 * @size:  the size of the array
14396 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14397 *             documents
14398 * @data:  the userdata
14399 *
14400 * parse an XML in-memory block and use the given SAX function block
14401 * to handle the parsing callback. If sax is NULL, fallback to the default
14402 * DOM tree building routines.
14403 *
14404 * User data (void *) is stored within the parser context in the
14405 * context's _private member, so it is available nearly everywhere in libxml
14406 *
14407 * Returns the resulting document tree
14408 */
14409
14410xmlDocPtr
14411xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14412	          int size, int recovery, void *data) {
14413    xmlDocPtr ret;
14414    xmlParserCtxtPtr ctxt;
14415
14416    xmlInitParser();
14417
14418    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14419    if (ctxt == NULL) return(NULL);
14420    if (sax != NULL) {
14421	if (ctxt->sax != NULL)
14422	    xmlFree(ctxt->sax);
14423        ctxt->sax = sax;
14424    }
14425    xmlDetectSAX2(ctxt);
14426    if (data!=NULL) {
14427	ctxt->_private=data;
14428    }
14429
14430    ctxt->recovery = recovery;
14431
14432    xmlParseDocument(ctxt);
14433
14434    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14435    else {
14436       ret = NULL;
14437       xmlFreeDoc(ctxt->myDoc);
14438       ctxt->myDoc = NULL;
14439    }
14440    if (sax != NULL)
14441	ctxt->sax = NULL;
14442    xmlFreeParserCtxt(ctxt);
14443
14444    return(ret);
14445}
14446
14447/**
14448 * xmlSAXParseMemory:
14449 * @sax:  the SAX handler block
14450 * @buffer:  an pointer to a char array
14451 * @size:  the size of the array
14452 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14453 *             documents
14454 *
14455 * parse an XML in-memory block and use the given SAX function block
14456 * to handle the parsing callback. If sax is NULL, fallback to the default
14457 * DOM tree building routines.
14458 *
14459 * Returns the resulting document tree
14460 */
14461xmlDocPtr
14462xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14463	          int size, int recovery) {
14464    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14465}
14466
14467/**
14468 * xmlParseMemory:
14469 * @buffer:  an pointer to a char array
14470 * @size:  the size of the array
14471 *
14472 * parse an XML in-memory block and build a tree.
14473 *
14474 * Returns the resulting document tree
14475 */
14476
14477xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14478   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14479}
14480
14481/**
14482 * xmlRecoverMemory:
14483 * @buffer:  an pointer to a char array
14484 * @size:  the size of the array
14485 *
14486 * parse an XML in-memory block and build a tree.
14487 * In the case the document is not Well Formed, an attempt to
14488 * build a tree is tried anyway
14489 *
14490 * Returns the resulting document tree or NULL in case of error
14491 */
14492
14493xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14494   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14495}
14496
14497/**
14498 * xmlSAXUserParseMemory:
14499 * @sax:  a SAX handler
14500 * @user_data:  The user data returned on SAX callbacks
14501 * @buffer:  an in-memory XML document input
14502 * @size:  the length of the XML document in bytes
14503 *
14504 * A better SAX parsing routine.
14505 * parse an XML in-memory buffer and call the given SAX handler routines.
14506 *
14507 * Returns 0 in case of success or a error number otherwise
14508 */
14509int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14510			  const char *buffer, int size) {
14511    int ret = 0;
14512    xmlParserCtxtPtr ctxt;
14513
14514    xmlInitParser();
14515
14516    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14517    if (ctxt == NULL) return -1;
14518    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14519        xmlFree(ctxt->sax);
14520    ctxt->sax = sax;
14521    xmlDetectSAX2(ctxt);
14522
14523    if (user_data != NULL)
14524	ctxt->userData = user_data;
14525
14526    xmlParseDocument(ctxt);
14527
14528    if (ctxt->wellFormed)
14529	ret = 0;
14530    else {
14531        if (ctxt->errNo != 0)
14532	    ret = ctxt->errNo;
14533	else
14534	    ret = -1;
14535    }
14536    if (sax != NULL)
14537        ctxt->sax = NULL;
14538    if (ctxt->myDoc != NULL) {
14539        xmlFreeDoc(ctxt->myDoc);
14540	ctxt->myDoc = NULL;
14541    }
14542    xmlFreeParserCtxt(ctxt);
14543
14544    return ret;
14545}
14546#endif /* LIBXML_SAX1_ENABLED */
14547
14548/**
14549 * xmlCreateDocParserCtxt:
14550 * @cur:  a pointer to an array of xmlChar
14551 *
14552 * Creates a parser context for an XML in-memory document.
14553 *
14554 * Returns the new parser context or NULL
14555 */
14556xmlParserCtxtPtr
14557xmlCreateDocParserCtxt(const xmlChar *cur) {
14558    int len;
14559
14560    if (cur == NULL)
14561	return(NULL);
14562    len = xmlStrlen(cur);
14563    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14564}
14565
14566#ifdef LIBXML_SAX1_ENABLED
14567/**
14568 * xmlSAXParseDoc:
14569 * @sax:  the SAX handler block
14570 * @cur:  a pointer to an array of xmlChar
14571 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14572 *             documents
14573 *
14574 * parse an XML in-memory document and build a tree.
14575 * It use the given SAX function block to handle the parsing callback.
14576 * If sax is NULL, fallback to the default DOM tree building routines.
14577 *
14578 * Returns the resulting document tree
14579 */
14580
14581xmlDocPtr
14582xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14583    xmlDocPtr ret;
14584    xmlParserCtxtPtr ctxt;
14585    xmlSAXHandlerPtr oldsax = NULL;
14586
14587    if (cur == NULL) return(NULL);
14588
14589
14590    ctxt = xmlCreateDocParserCtxt(cur);
14591    if (ctxt == NULL) return(NULL);
14592    if (sax != NULL) {
14593        oldsax = ctxt->sax;
14594        ctxt->sax = sax;
14595        ctxt->userData = NULL;
14596    }
14597    xmlDetectSAX2(ctxt);
14598
14599    xmlParseDocument(ctxt);
14600    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14601    else {
14602       ret = NULL;
14603       xmlFreeDoc(ctxt->myDoc);
14604       ctxt->myDoc = NULL;
14605    }
14606    if (sax != NULL)
14607	ctxt->sax = oldsax;
14608    xmlFreeParserCtxt(ctxt);
14609
14610    return(ret);
14611}
14612
14613/**
14614 * xmlParseDoc:
14615 * @cur:  a pointer to an array of xmlChar
14616 *
14617 * parse an XML in-memory document and build a tree.
14618 *
14619 * Returns the resulting document tree
14620 */
14621
14622xmlDocPtr
14623xmlParseDoc(const xmlChar *cur) {
14624    return(xmlSAXParseDoc(NULL, cur, 0));
14625}
14626#endif /* LIBXML_SAX1_ENABLED */
14627
14628#ifdef LIBXML_LEGACY_ENABLED
14629/************************************************************************
14630 *									*
14631 *	Specific function to keep track of entities references		*
14632 *	and used by the XSLT debugger					*
14633 *									*
14634 ************************************************************************/
14635
14636static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14637
14638/**
14639 * xmlAddEntityReference:
14640 * @ent : A valid entity
14641 * @firstNode : A valid first node for children of entity
14642 * @lastNode : A valid last node of children entity
14643 *
14644 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14645 */
14646static void
14647xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14648                      xmlNodePtr lastNode)
14649{
14650    if (xmlEntityRefFunc != NULL) {
14651        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14652    }
14653}
14654
14655
14656/**
14657 * xmlSetEntityReferenceFunc:
14658 * @func: A valid function
14659 *
14660 * Set the function to call call back when a xml reference has been made
14661 */
14662void
14663xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14664{
14665    xmlEntityRefFunc = func;
14666}
14667#endif /* LIBXML_LEGACY_ENABLED */
14668
14669/************************************************************************
14670 *									*
14671 *				Miscellaneous				*
14672 *									*
14673 ************************************************************************/
14674
14675#ifdef LIBXML_XPATH_ENABLED
14676#include <libxml/xpath.h>
14677#endif
14678
14679extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
14680static int xmlParserInitialized = 0;
14681
14682/**
14683 * xmlInitParser:
14684 *
14685 * Initialization function for the XML parser.
14686 * This is not reentrant. Call once before processing in case of
14687 * use in multithreaded programs.
14688 */
14689
14690void
14691xmlInitParser(void) {
14692    if (xmlParserInitialized != 0)
14693	return;
14694
14695#ifdef LIBXML_THREAD_ENABLED
14696    __xmlGlobalInitMutexLock();
14697    if (xmlParserInitialized == 0) {
14698#endif
14699	xmlInitThreads();
14700	xmlInitGlobals();
14701	if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
14702	    (xmlGenericError == NULL))
14703	    initGenericErrorDefaultFunc(NULL);
14704	xmlInitMemory();
14705        xmlInitializeDict();
14706	xmlInitCharEncodingHandlers();
14707	xmlDefaultSAXHandlerInit();
14708	xmlRegisterDefaultInputCallbacks();
14709#ifdef LIBXML_OUTPUT_ENABLED
14710	xmlRegisterDefaultOutputCallbacks();
14711#endif /* LIBXML_OUTPUT_ENABLED */
14712#ifdef LIBXML_HTML_ENABLED
14713	htmlInitAutoClose();
14714	htmlDefaultSAXHandlerInit();
14715#endif
14716#ifdef LIBXML_XPATH_ENABLED
14717	xmlXPathInit();
14718#endif
14719	xmlParserInitialized = 1;
14720#ifdef LIBXML_THREAD_ENABLED
14721    }
14722    __xmlGlobalInitMutexUnlock();
14723#endif
14724}
14725
14726/**
14727 * xmlCleanupParser:
14728 *
14729 * This function name is somewhat misleading. It does not clean up
14730 * parser state, it cleans up memory allocated by the library itself.
14731 * It is a cleanup function for the XML library. It tries to reclaim all
14732 * related global memory allocated for the library processing.
14733 * It doesn't deallocate any document related memory. One should
14734 * call xmlCleanupParser() only when the process has finished using
14735 * the library and all XML/HTML documents built with it.
14736 * See also xmlInitParser() which has the opposite function of preparing
14737 * the library for operations.
14738 *
14739 * WARNING: if your application is multithreaded or has plugin support
14740 *          calling this may crash the application if another thread or
14741 *          a plugin is still using libxml2. It's sometimes very hard to
14742 *          guess if libxml2 is in use in the application, some libraries
14743 *          or plugins may use it without notice. In case of doubt abstain
14744 *          from calling this function or do it just before calling exit()
14745 *          to avoid leak reports from valgrind !
14746 */
14747
14748void
14749xmlCleanupParser(void) {
14750    if (!xmlParserInitialized)
14751	return;
14752
14753    xmlCleanupCharEncodingHandlers();
14754#ifdef LIBXML_CATALOG_ENABLED
14755    xmlCatalogCleanup();
14756#endif
14757    xmlDictCleanup();
14758    xmlCleanupInputCallbacks();
14759#ifdef LIBXML_OUTPUT_ENABLED
14760    xmlCleanupOutputCallbacks();
14761#endif
14762#ifdef LIBXML_SCHEMAS_ENABLED
14763    xmlSchemaCleanupTypes();
14764    xmlRelaxNGCleanupTypes();
14765#endif
14766    xmlCleanupGlobals();
14767    xmlResetLastError();
14768    xmlCleanupThreads(); /* must be last if called not from the main thread */
14769    xmlCleanupMemory();
14770    xmlParserInitialized = 0;
14771}
14772
14773/************************************************************************
14774 *									*
14775 *	New set (2.6.0) of simpler and more flexible APIs		*
14776 *									*
14777 ************************************************************************/
14778
14779/**
14780 * DICT_FREE:
14781 * @str:  a string
14782 *
14783 * Free a string if it is not owned by the "dict" dictionnary in the
14784 * current scope
14785 */
14786#define DICT_FREE(str)						\
14787	if ((str) && ((!dict) ||				\
14788	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
14789	    xmlFree((char *)(str));
14790
14791/**
14792 * xmlCtxtReset:
14793 * @ctxt: an XML parser context
14794 *
14795 * Reset a parser context
14796 */
14797void
14798xmlCtxtReset(xmlParserCtxtPtr ctxt)
14799{
14800    xmlParserInputPtr input;
14801    xmlDictPtr dict;
14802
14803    if (ctxt == NULL)
14804        return;
14805
14806    dict = ctxt->dict;
14807
14808    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14809        xmlFreeInputStream(input);
14810    }
14811    ctxt->inputNr = 0;
14812    ctxt->input = NULL;
14813
14814    ctxt->spaceNr = 0;
14815    if (ctxt->spaceTab != NULL) {
14816	ctxt->spaceTab[0] = -1;
14817	ctxt->space = &ctxt->spaceTab[0];
14818    } else {
14819        ctxt->space = NULL;
14820    }
14821
14822
14823    ctxt->nodeNr = 0;
14824    ctxt->node = NULL;
14825
14826    ctxt->nameNr = 0;
14827    ctxt->name = NULL;
14828
14829    DICT_FREE(ctxt->version);
14830    ctxt->version = NULL;
14831    DICT_FREE(ctxt->encoding);
14832    ctxt->encoding = NULL;
14833    DICT_FREE(ctxt->directory);
14834    ctxt->directory = NULL;
14835    DICT_FREE(ctxt->extSubURI);
14836    ctxt->extSubURI = NULL;
14837    DICT_FREE(ctxt->extSubSystem);
14838    ctxt->extSubSystem = NULL;
14839    if (ctxt->myDoc != NULL)
14840        xmlFreeDoc(ctxt->myDoc);
14841    ctxt->myDoc = NULL;
14842
14843    ctxt->standalone = -1;
14844    ctxt->hasExternalSubset = 0;
14845    ctxt->hasPErefs = 0;
14846    ctxt->html = 0;
14847    ctxt->external = 0;
14848    ctxt->instate = XML_PARSER_START;
14849    ctxt->token = 0;
14850
14851    ctxt->wellFormed = 1;
14852    ctxt->nsWellFormed = 1;
14853    ctxt->disableSAX = 0;
14854    ctxt->valid = 1;
14855#if 0
14856    ctxt->vctxt.userData = ctxt;
14857    ctxt->vctxt.error = xmlParserValidityError;
14858    ctxt->vctxt.warning = xmlParserValidityWarning;
14859#endif
14860    ctxt->record_info = 0;
14861    ctxt->nbChars = 0;
14862    ctxt->checkIndex = 0;
14863    ctxt->inSubset = 0;
14864    ctxt->errNo = XML_ERR_OK;
14865    ctxt->depth = 0;
14866    ctxt->charset = XML_CHAR_ENCODING_UTF8;
14867    ctxt->catalogs = NULL;
14868    ctxt->nbentities = 0;
14869    ctxt->sizeentities = 0;
14870    ctxt->sizeentcopy = 0;
14871    xmlInitNodeInfoSeq(&ctxt->node_seq);
14872
14873    if (ctxt->attsDefault != NULL) {
14874        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
14875        ctxt->attsDefault = NULL;
14876    }
14877    if (ctxt->attsSpecial != NULL) {
14878        xmlHashFree(ctxt->attsSpecial, NULL);
14879        ctxt->attsSpecial = NULL;
14880    }
14881
14882#ifdef LIBXML_CATALOG_ENABLED
14883    if (ctxt->catalogs != NULL)
14884	xmlCatalogFreeLocal(ctxt->catalogs);
14885#endif
14886    if (ctxt->lastError.code != XML_ERR_OK)
14887        xmlResetError(&ctxt->lastError);
14888}
14889
14890/**
14891 * xmlCtxtResetPush:
14892 * @ctxt: an XML parser context
14893 * @chunk:  a pointer to an array of chars
14894 * @size:  number of chars in the array
14895 * @filename:  an optional file name or URI
14896 * @encoding:  the document encoding, or NULL
14897 *
14898 * Reset a push parser context
14899 *
14900 * Returns 0 in case of success and 1 in case of error
14901 */
14902int
14903xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14904                 int size, const char *filename, const char *encoding)
14905{
14906    xmlParserInputPtr inputStream;
14907    xmlParserInputBufferPtr buf;
14908    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14909
14910    if (ctxt == NULL)
14911        return(1);
14912
14913    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14914        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14915
14916    buf = xmlAllocParserInputBuffer(enc);
14917    if (buf == NULL)
14918        return(1);
14919
14920    if (ctxt == NULL) {
14921        xmlFreeParserInputBuffer(buf);
14922        return(1);
14923    }
14924
14925    xmlCtxtReset(ctxt);
14926
14927    if (ctxt->pushTab == NULL) {
14928        ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
14929	                                    sizeof(xmlChar *));
14930        if (ctxt->pushTab == NULL) {
14931	    xmlErrMemory(ctxt, NULL);
14932            xmlFreeParserInputBuffer(buf);
14933            return(1);
14934        }
14935    }
14936
14937    if (filename == NULL) {
14938        ctxt->directory = NULL;
14939    } else {
14940        ctxt->directory = xmlParserGetDirectory(filename);
14941    }
14942
14943    inputStream = xmlNewInputStream(ctxt);
14944    if (inputStream == NULL) {
14945        xmlFreeParserInputBuffer(buf);
14946        return(1);
14947    }
14948
14949    if (filename == NULL)
14950        inputStream->filename = NULL;
14951    else
14952        inputStream->filename = (char *)
14953            xmlCanonicPath((const xmlChar *) filename);
14954    inputStream->buf = buf;
14955    xmlBufResetInput(buf->buffer, inputStream);
14956
14957    inputPush(ctxt, inputStream);
14958
14959    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14960        (ctxt->input->buf != NULL)) {
14961	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
14962        size_t cur = ctxt->input->cur - ctxt->input->base;
14963
14964        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14965
14966        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
14967#ifdef DEBUG_PUSH
14968        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
14969#endif
14970    }
14971
14972    if (encoding != NULL) {
14973        xmlCharEncodingHandlerPtr hdlr;
14974
14975        if (ctxt->encoding != NULL)
14976	    xmlFree((xmlChar *) ctxt->encoding);
14977        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14978
14979        hdlr = xmlFindCharEncodingHandler(encoding);
14980        if (hdlr != NULL) {
14981            xmlSwitchToEncoding(ctxt, hdlr);
14982	} else {
14983	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14984			      "Unsupported encoding %s\n", BAD_CAST encoding);
14985        }
14986    } else if (enc != XML_CHAR_ENCODING_NONE) {
14987        xmlSwitchEncoding(ctxt, enc);
14988    }
14989
14990    return(0);
14991}
14992
14993
14994/**
14995 * xmlCtxtUseOptionsInternal:
14996 * @ctxt: an XML parser context
14997 * @options:  a combination of xmlParserOption
14998 * @encoding:  the user provided encoding to use
14999 *
15000 * Applies the options to the parser context
15001 *
15002 * Returns 0 in case of success, the set of unknown or unimplemented options
15003 *         in case of error.
15004 */
15005static int
15006xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
15007{
15008    if (ctxt == NULL)
15009        return(-1);
15010    if (encoding != NULL) {
15011        if (ctxt->encoding != NULL)
15012	    xmlFree((xmlChar *) ctxt->encoding);
15013        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15014    }
15015    if (options & XML_PARSE_RECOVER) {
15016        ctxt->recovery = 1;
15017        options -= XML_PARSE_RECOVER;
15018	ctxt->options |= XML_PARSE_RECOVER;
15019    } else
15020        ctxt->recovery = 0;
15021    if (options & XML_PARSE_DTDLOAD) {
15022        ctxt->loadsubset = XML_DETECT_IDS;
15023        options -= XML_PARSE_DTDLOAD;
15024	ctxt->options |= XML_PARSE_DTDLOAD;
15025    } else
15026        ctxt->loadsubset = 0;
15027    if (options & XML_PARSE_DTDATTR) {
15028        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
15029        options -= XML_PARSE_DTDATTR;
15030	ctxt->options |= XML_PARSE_DTDATTR;
15031    }
15032    if (options & XML_PARSE_NOENT) {
15033        ctxt->replaceEntities = 1;
15034        /* ctxt->loadsubset |= XML_DETECT_IDS; */
15035        options -= XML_PARSE_NOENT;
15036	ctxt->options |= XML_PARSE_NOENT;
15037    } else
15038        ctxt->replaceEntities = 0;
15039    if (options & XML_PARSE_PEDANTIC) {
15040        ctxt->pedantic = 1;
15041        options -= XML_PARSE_PEDANTIC;
15042	ctxt->options |= XML_PARSE_PEDANTIC;
15043    } else
15044        ctxt->pedantic = 0;
15045    if (options & XML_PARSE_NOBLANKS) {
15046        ctxt->keepBlanks = 0;
15047        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
15048        options -= XML_PARSE_NOBLANKS;
15049	ctxt->options |= XML_PARSE_NOBLANKS;
15050    } else
15051        ctxt->keepBlanks = 1;
15052    if (options & XML_PARSE_DTDVALID) {
15053        ctxt->validate = 1;
15054        if (options & XML_PARSE_NOWARNING)
15055            ctxt->vctxt.warning = NULL;
15056        if (options & XML_PARSE_NOERROR)
15057            ctxt->vctxt.error = NULL;
15058        options -= XML_PARSE_DTDVALID;
15059	ctxt->options |= XML_PARSE_DTDVALID;
15060    } else
15061        ctxt->validate = 0;
15062    if (options & XML_PARSE_NOWARNING) {
15063        ctxt->sax->warning = NULL;
15064        options -= XML_PARSE_NOWARNING;
15065    }
15066    if (options & XML_PARSE_NOERROR) {
15067        ctxt->sax->error = NULL;
15068        ctxt->sax->fatalError = NULL;
15069        options -= XML_PARSE_NOERROR;
15070    }
15071#ifdef LIBXML_SAX1_ENABLED
15072    if (options & XML_PARSE_SAX1) {
15073        ctxt->sax->startElement = xmlSAX2StartElement;
15074        ctxt->sax->endElement = xmlSAX2EndElement;
15075        ctxt->sax->startElementNs = NULL;
15076        ctxt->sax->endElementNs = NULL;
15077        ctxt->sax->initialized = 1;
15078        options -= XML_PARSE_SAX1;
15079	ctxt->options |= XML_PARSE_SAX1;
15080    }
15081#endif /* LIBXML_SAX1_ENABLED */
15082    if (options & XML_PARSE_NODICT) {
15083        ctxt->dictNames = 0;
15084        options -= XML_PARSE_NODICT;
15085	ctxt->options |= XML_PARSE_NODICT;
15086    } else {
15087        ctxt->dictNames = 1;
15088    }
15089    if (options & XML_PARSE_NOCDATA) {
15090        ctxt->sax->cdataBlock = NULL;
15091        options -= XML_PARSE_NOCDATA;
15092	ctxt->options |= XML_PARSE_NOCDATA;
15093    }
15094    if (options & XML_PARSE_NSCLEAN) {
15095	ctxt->options |= XML_PARSE_NSCLEAN;
15096        options -= XML_PARSE_NSCLEAN;
15097    }
15098    if (options & XML_PARSE_NONET) {
15099	ctxt->options |= XML_PARSE_NONET;
15100        options -= XML_PARSE_NONET;
15101    }
15102    if (options & XML_PARSE_COMPACT) {
15103	ctxt->options |= XML_PARSE_COMPACT;
15104        options -= XML_PARSE_COMPACT;
15105    }
15106    if (options & XML_PARSE_OLD10) {
15107	ctxt->options |= XML_PARSE_OLD10;
15108        options -= XML_PARSE_OLD10;
15109    }
15110    if (options & XML_PARSE_NOBASEFIX) {
15111	ctxt->options |= XML_PARSE_NOBASEFIX;
15112        options -= XML_PARSE_NOBASEFIX;
15113    }
15114    if (options & XML_PARSE_HUGE) {
15115	ctxt->options |= XML_PARSE_HUGE;
15116        options -= XML_PARSE_HUGE;
15117        if (ctxt->dict != NULL)
15118            xmlDictSetLimit(ctxt->dict, 0);
15119    }
15120    if (options & XML_PARSE_OLDSAX) {
15121	ctxt->options |= XML_PARSE_OLDSAX;
15122        options -= XML_PARSE_OLDSAX;
15123    }
15124    if (options & XML_PARSE_IGNORE_ENC) {
15125	ctxt->options |= XML_PARSE_IGNORE_ENC;
15126        options -= XML_PARSE_IGNORE_ENC;
15127    }
15128    if (options & XML_PARSE_BIG_LINES) {
15129	ctxt->options |= XML_PARSE_BIG_LINES;
15130        options -= XML_PARSE_BIG_LINES;
15131    }
15132    ctxt->linenumbers = 1;
15133    return (options);
15134}
15135
15136/**
15137 * xmlCtxtUseOptions:
15138 * @ctxt: an XML parser context
15139 * @options:  a combination of xmlParserOption
15140 *
15141 * Applies the options to the parser context
15142 *
15143 * Returns 0 in case of success, the set of unknown or unimplemented options
15144 *         in case of error.
15145 */
15146int
15147xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
15148{
15149   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
15150}
15151
15152/**
15153 * xmlDoRead:
15154 * @ctxt:  an XML parser context
15155 * @URL:  the base URL to use for the document
15156 * @encoding:  the document encoding, or NULL
15157 * @options:  a combination of xmlParserOption
15158 * @reuse:  keep the context for reuse
15159 *
15160 * Common front-end for the xmlRead functions
15161 *
15162 * Returns the resulting document tree or NULL
15163 */
15164static xmlDocPtr
15165xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
15166          int options, int reuse)
15167{
15168    xmlDocPtr ret;
15169
15170    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
15171    if (encoding != NULL) {
15172        xmlCharEncodingHandlerPtr hdlr;
15173
15174	hdlr = xmlFindCharEncodingHandler(encoding);
15175	if (hdlr != NULL)
15176	    xmlSwitchToEncoding(ctxt, hdlr);
15177    }
15178    if ((URL != NULL) && (ctxt->input != NULL) &&
15179        (ctxt->input->filename == NULL))
15180        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
15181    xmlParseDocument(ctxt);
15182    if ((ctxt->wellFormed) || ctxt->recovery)
15183        ret = ctxt->myDoc;
15184    else {
15185        ret = NULL;
15186	if (ctxt->myDoc != NULL) {
15187	    xmlFreeDoc(ctxt->myDoc);
15188	}
15189    }
15190    ctxt->myDoc = NULL;
15191    if (!reuse) {
15192	xmlFreeParserCtxt(ctxt);
15193    }
15194
15195    return (ret);
15196}
15197
15198/**
15199 * xmlReadDoc:
15200 * @cur:  a pointer to a zero terminated string
15201 * @URL:  the base URL to use for the document
15202 * @encoding:  the document encoding, or NULL
15203 * @options:  a combination of xmlParserOption
15204 *
15205 * parse an XML in-memory document and build a tree.
15206 *
15207 * Returns the resulting document tree
15208 */
15209xmlDocPtr
15210xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
15211{
15212    xmlParserCtxtPtr ctxt;
15213
15214    if (cur == NULL)
15215        return (NULL);
15216
15217    ctxt = xmlCreateDocParserCtxt(cur);
15218    if (ctxt == NULL)
15219        return (NULL);
15220    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15221}
15222
15223/**
15224 * xmlReadFile:
15225 * @filename:  a file or URL
15226 * @encoding:  the document encoding, or NULL
15227 * @options:  a combination of xmlParserOption
15228 *
15229 * parse an XML file from the filesystem or the network.
15230 *
15231 * Returns the resulting document tree
15232 */
15233xmlDocPtr
15234xmlReadFile(const char *filename, const char *encoding, int options)
15235{
15236    xmlParserCtxtPtr ctxt;
15237
15238    ctxt = xmlCreateURLParserCtxt(filename, options);
15239    if (ctxt == NULL)
15240        return (NULL);
15241    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
15242}
15243
15244/**
15245 * xmlReadMemory:
15246 * @buffer:  a pointer to a char array
15247 * @size:  the size of the array
15248 * @URL:  the base URL to use for the document
15249 * @encoding:  the document encoding, or NULL
15250 * @options:  a combination of xmlParserOption
15251 *
15252 * parse an XML in-memory document and build a tree.
15253 *
15254 * Returns the resulting document tree
15255 */
15256xmlDocPtr
15257xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
15258{
15259    xmlParserCtxtPtr ctxt;
15260
15261    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
15262    if (ctxt == NULL)
15263        return (NULL);
15264    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15265}
15266
15267/**
15268 * xmlReadFd:
15269 * @fd:  an open file descriptor
15270 * @URL:  the base URL to use for the document
15271 * @encoding:  the document encoding, or NULL
15272 * @options:  a combination of xmlParserOption
15273 *
15274 * parse an XML from a file descriptor and build a tree.
15275 * NOTE that the file descriptor will not be closed when the
15276 *      reader is closed or reset.
15277 *
15278 * Returns the resulting document tree
15279 */
15280xmlDocPtr
15281xmlReadFd(int fd, const char *URL, const char *encoding, int options)
15282{
15283    xmlParserCtxtPtr ctxt;
15284    xmlParserInputBufferPtr input;
15285    xmlParserInputPtr stream;
15286
15287    if (fd < 0)
15288        return (NULL);
15289
15290    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15291    if (input == NULL)
15292        return (NULL);
15293    input->closecallback = NULL;
15294    ctxt = xmlNewParserCtxt();
15295    if (ctxt == NULL) {
15296        xmlFreeParserInputBuffer(input);
15297        return (NULL);
15298    }
15299    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15300    if (stream == NULL) {
15301        xmlFreeParserInputBuffer(input);
15302	xmlFreeParserCtxt(ctxt);
15303        return (NULL);
15304    }
15305    inputPush(ctxt, stream);
15306    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15307}
15308
15309/**
15310 * xmlReadIO:
15311 * @ioread:  an I/O read function
15312 * @ioclose:  an I/O close function
15313 * @ioctx:  an I/O handler
15314 * @URL:  the base URL to use for the document
15315 * @encoding:  the document encoding, or NULL
15316 * @options:  a combination of xmlParserOption
15317 *
15318 * parse an XML document from I/O functions and source and build a tree.
15319 *
15320 * Returns the resulting document tree
15321 */
15322xmlDocPtr
15323xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
15324          void *ioctx, const char *URL, const char *encoding, int options)
15325{
15326    xmlParserCtxtPtr ctxt;
15327    xmlParserInputBufferPtr input;
15328    xmlParserInputPtr stream;
15329
15330    if (ioread == NULL)
15331        return (NULL);
15332
15333    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15334                                         XML_CHAR_ENCODING_NONE);
15335    if (input == NULL) {
15336        if (ioclose != NULL)
15337            ioclose(ioctx);
15338        return (NULL);
15339    }
15340    ctxt = xmlNewParserCtxt();
15341    if (ctxt == NULL) {
15342        xmlFreeParserInputBuffer(input);
15343        return (NULL);
15344    }
15345    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15346    if (stream == NULL) {
15347        xmlFreeParserInputBuffer(input);
15348	xmlFreeParserCtxt(ctxt);
15349        return (NULL);
15350    }
15351    inputPush(ctxt, stream);
15352    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15353}
15354
15355/**
15356 * xmlCtxtReadDoc:
15357 * @ctxt:  an XML parser context
15358 * @cur:  a pointer to a zero terminated string
15359 * @URL:  the base URL to use for the document
15360 * @encoding:  the document encoding, or NULL
15361 * @options:  a combination of xmlParserOption
15362 *
15363 * parse an XML in-memory document and build a tree.
15364 * This reuses the existing @ctxt parser context
15365 *
15366 * Returns the resulting document tree
15367 */
15368xmlDocPtr
15369xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
15370               const char *URL, const char *encoding, int options)
15371{
15372    xmlParserInputPtr stream;
15373
15374    if (cur == NULL)
15375        return (NULL);
15376    if (ctxt == NULL)
15377        return (NULL);
15378
15379    xmlCtxtReset(ctxt);
15380
15381    stream = xmlNewStringInputStream(ctxt, cur);
15382    if (stream == NULL) {
15383        return (NULL);
15384    }
15385    inputPush(ctxt, stream);
15386    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15387}
15388
15389/**
15390 * xmlCtxtReadFile:
15391 * @ctxt:  an XML parser context
15392 * @filename:  a file or URL
15393 * @encoding:  the document encoding, or NULL
15394 * @options:  a combination of xmlParserOption
15395 *
15396 * parse an XML file from the filesystem or the network.
15397 * This reuses the existing @ctxt parser context
15398 *
15399 * Returns the resulting document tree
15400 */
15401xmlDocPtr
15402xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15403                const char *encoding, int options)
15404{
15405    xmlParserInputPtr stream;
15406
15407    if (filename == NULL)
15408        return (NULL);
15409    if (ctxt == NULL)
15410        return (NULL);
15411
15412    xmlCtxtReset(ctxt);
15413
15414    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15415    if (stream == NULL) {
15416        return (NULL);
15417    }
15418    inputPush(ctxt, stream);
15419    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15420}
15421
15422/**
15423 * xmlCtxtReadMemory:
15424 * @ctxt:  an XML parser context
15425 * @buffer:  a pointer to a char array
15426 * @size:  the size of the array
15427 * @URL:  the base URL to use for the document
15428 * @encoding:  the document encoding, or NULL
15429 * @options:  a combination of xmlParserOption
15430 *
15431 * parse an XML in-memory document and build a tree.
15432 * This reuses the existing @ctxt parser context
15433 *
15434 * Returns the resulting document tree
15435 */
15436xmlDocPtr
15437xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15438                  const char *URL, const char *encoding, int options)
15439{
15440    xmlParserInputBufferPtr input;
15441    xmlParserInputPtr stream;
15442
15443    if (ctxt == NULL)
15444        return (NULL);
15445    if (buffer == NULL)
15446        return (NULL);
15447
15448    xmlCtxtReset(ctxt);
15449
15450    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
15451    if (input == NULL) {
15452	return(NULL);
15453    }
15454
15455    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15456    if (stream == NULL) {
15457	xmlFreeParserInputBuffer(input);
15458	return(NULL);
15459    }
15460
15461    inputPush(ctxt, stream);
15462    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15463}
15464
15465/**
15466 * xmlCtxtReadFd:
15467 * @ctxt:  an XML parser context
15468 * @fd:  an open file descriptor
15469 * @URL:  the base URL to use for the document
15470 * @encoding:  the document encoding, or NULL
15471 * @options:  a combination of xmlParserOption
15472 *
15473 * parse an XML from a file descriptor and build a tree.
15474 * This reuses the existing @ctxt parser context
15475 * NOTE that the file descriptor will not be closed when the
15476 *      reader is closed or reset.
15477 *
15478 * Returns the resulting document tree
15479 */
15480xmlDocPtr
15481xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15482              const char *URL, const char *encoding, int options)
15483{
15484    xmlParserInputBufferPtr input;
15485    xmlParserInputPtr stream;
15486
15487    if (fd < 0)
15488        return (NULL);
15489    if (ctxt == NULL)
15490        return (NULL);
15491
15492    xmlCtxtReset(ctxt);
15493
15494
15495    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15496    if (input == NULL)
15497        return (NULL);
15498    input->closecallback = NULL;
15499    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15500    if (stream == NULL) {
15501        xmlFreeParserInputBuffer(input);
15502        return (NULL);
15503    }
15504    inputPush(ctxt, stream);
15505    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15506}
15507
15508/**
15509 * xmlCtxtReadIO:
15510 * @ctxt:  an XML parser context
15511 * @ioread:  an I/O read function
15512 * @ioclose:  an I/O close function
15513 * @ioctx:  an I/O handler
15514 * @URL:  the base URL to use for the document
15515 * @encoding:  the document encoding, or NULL
15516 * @options:  a combination of xmlParserOption
15517 *
15518 * parse an XML document from I/O functions and source and build a tree.
15519 * This reuses the existing @ctxt parser context
15520 *
15521 * Returns the resulting document tree
15522 */
15523xmlDocPtr
15524xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15525              xmlInputCloseCallback ioclose, void *ioctx,
15526	      const char *URL,
15527              const char *encoding, int options)
15528{
15529    xmlParserInputBufferPtr input;
15530    xmlParserInputPtr stream;
15531
15532    if (ioread == NULL)
15533        return (NULL);
15534    if (ctxt == NULL)
15535        return (NULL);
15536
15537    xmlCtxtReset(ctxt);
15538
15539    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15540                                         XML_CHAR_ENCODING_NONE);
15541    if (input == NULL) {
15542        if (ioclose != NULL)
15543            ioclose(ioctx);
15544        return (NULL);
15545    }
15546    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15547    if (stream == NULL) {
15548        xmlFreeParserInputBuffer(input);
15549        return (NULL);
15550    }
15551    inputPush(ctxt, stream);
15552    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15553}
15554
15555#define bottom_parser
15556#include "elfgcchack.h"
15557