upload tizen1.0 source
[external/libxml2.git] / parser.c
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 <string.h>
44 #include <stdarg.h>
45 #include <libxml/xmlmemory.h>
46 #include <libxml/threads.h>
47 #include <libxml/globals.h>
48 #include <libxml/tree.h>
49 #include <libxml/parser.h>
50 #include <libxml/parserInternals.h>
51 #include <libxml/valid.h>
52 #include <libxml/entities.h>
53 #include <libxml/xmlerror.h>
54 #include <libxml/encoding.h>
55 #include <libxml/xmlIO.h>
56 #include <libxml/uri.h>
57 #ifdef LIBXML_CATALOG_ENABLED
58 #include <libxml/catalog.h>
59 #endif
60 #ifdef LIBXML_SCHEMAS_ENABLED
61 #include <libxml/xmlschemastypes.h>
62 #include <libxml/relaxng.h>
63 #endif
64 #ifdef HAVE_CTYPE_H
65 #include <ctype.h>
66 #endif
67 #ifdef HAVE_STDLIB_H
68 #include <stdlib.h>
69 #endif
70 #ifdef HAVE_SYS_STAT_H
71 #include <sys/stat.h>
72 #endif
73 #ifdef HAVE_FCNTL_H
74 #include <fcntl.h>
75 #endif
76 #ifdef HAVE_UNISTD_H
77 #include <unistd.h>
78 #endif
79 #ifdef HAVE_ZLIB_H
80 #include <zlib.h>
81 #endif
82
83 static void
84 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
85
86 static xmlParserCtxtPtr
87 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
88                           const xmlChar *base, xmlParserCtxtPtr pctx);
89
90 /************************************************************************
91  *                                                                      *
92  *      Arbitrary limits set in the parser. See XML_PARSE_HUGE          *
93  *                                                                      *
94  ************************************************************************/
95
96 #define XML_PARSER_BIG_ENTITY 1000
97 #define XML_PARSER_LOT_ENTITY 5000
98
99 /*
100  * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
101  *    replacement over the size in byte of the input indicates that you have
102  *    and eponential behaviour. A value of 10 correspond to at least 3 entity
103  *    replacement per byte of input.
104  */
105 #define XML_PARSER_NON_LINEAR 10
106
107 /*
108  * xmlParserEntityCheck
109  *
110  * Function to check non-linear entity expansion behaviour
111  * This is here to detect and stop exponential linear entity expansion
112  * This is not a limitation of the parser but a safety
113  * boundary feature. It can be disabled with the XML_PARSE_HUGE
114  * parser option.
115  */
116 static int
117 xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
118                      xmlEntityPtr ent)
119 {
120     unsigned long consumed = 0;
121
122     if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
123         return (0);
124     if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
125         return (1);
126     if (size != 0) {
127         /*
128          * Do the check based on the replacement size of the entity
129          */
130         if (size < XML_PARSER_BIG_ENTITY)
131             return(0);
132
133         /*
134          * A limit on the amount of text data reasonably used
135          */
136         if (ctxt->input != NULL) {
137             consumed = ctxt->input->consumed +
138                 (ctxt->input->cur - ctxt->input->base);
139         }
140         consumed += ctxt->sizeentities;
141
142         if ((size < XML_PARSER_NON_LINEAR * consumed) &&
143             (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
144             return (0);
145     } else if (ent != NULL) {
146         /*
147          * use the number of parsed entities in the replacement
148          */
149         size = ent->checked;
150
151         /*
152          * The amount of data parsed counting entities size only once
153          */
154         if (ctxt->input != NULL) {
155             consumed = ctxt->input->consumed +
156                 (ctxt->input->cur - ctxt->input->base);
157         }
158         consumed += ctxt->sizeentities;
159
160         /*
161          * Check the density of entities for the amount of data
162          * knowing an entity reference will take at least 3 bytes
163          */
164         if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
165             return (0);
166     } else {
167         /*
168          * strange we got no data for checking just return
169          */
170         return (0);
171     }
172
173     xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
174     return (1);
175 }
176
177 /**
178  * xmlParserMaxDepth:
179  *
180  * arbitrary depth limit for the XML documents that we allow to
181  * process. This is not a limitation of the parser but a safety
182  * boundary feature. It can be disabled with the XML_PARSE_HUGE
183  * parser option.
184  */
185 unsigned int xmlParserMaxDepth = 256;
186
187
188
189 #define SAX2 1
190 #define XML_PARSER_BIG_BUFFER_SIZE 300
191 #define XML_PARSER_BUFFER_SIZE 100
192 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
193
194 /*
195  * List of XML prefixed PI allowed by W3C specs
196  */
197
198 static const char *xmlW3CPIs[] = {
199     "xml-stylesheet",
200     NULL
201 };
202
203
204 /* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
205 static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
206                                               const xmlChar **str);
207
208 static xmlParserErrors
209 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
210                       xmlSAXHandlerPtr sax,
211                       void *user_data, int depth, const xmlChar *URL,
212                       const xmlChar *ID, xmlNodePtr *list);
213
214 static int
215 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
216                           const char *encoding);
217 #ifdef LIBXML_LEGACY_ENABLED
218 static void
219 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
220                       xmlNodePtr lastNode);
221 #endif /* LIBXML_LEGACY_ENABLED */
222
223 static xmlParserErrors
224 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
225                       const xmlChar *string, void *user_data, xmlNodePtr *lst);
226
227 static int
228 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
229
230 /************************************************************************
231  *                                                                      *
232  *              Some factorized error routines                          *
233  *                                                                      *
234  ************************************************************************/
235
236 /**
237  * xmlErrAttributeDup:
238  * @ctxt:  an XML parser context
239  * @prefix:  the attribute prefix
240  * @localname:  the attribute localname
241  *
242  * Handle a redefinition of attribute error
243  */
244 static void
245 xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
246                    const xmlChar * localname)
247 {
248     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
249         (ctxt->instate == XML_PARSER_EOF))
250         return;
251     if (ctxt != NULL)
252         ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
253
254     if (prefix == NULL)
255         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
256                         XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
257                         (const char *) localname, NULL, NULL, 0, 0,
258                         "Attribute %s redefined\n", localname);
259     else
260         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
261                         XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
262                         (const char *) prefix, (const char *) localname,
263                         NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
264                         localname);
265     if (ctxt != NULL) {
266         ctxt->wellFormed = 0;
267         if (ctxt->recovery == 0)
268             ctxt->disableSAX = 1;
269     }
270 }
271
272 /**
273  * xmlFatalErr:
274  * @ctxt:  an XML parser context
275  * @error:  the error number
276  * @extra:  extra information string
277  *
278  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
279  */
280 static void
281 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
282 {
283     const char *errmsg;
284
285     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
286         (ctxt->instate == XML_PARSER_EOF))
287         return;
288     switch (error) {
289         case XML_ERR_INVALID_HEX_CHARREF:
290             errmsg = "CharRef: invalid hexadecimal value\n";
291             break;
292         case XML_ERR_INVALID_DEC_CHARREF:
293             errmsg = "CharRef: invalid decimal value\n";
294             break;
295         case XML_ERR_INVALID_CHARREF:
296             errmsg = "CharRef: invalid value\n";
297             break;
298         case XML_ERR_INTERNAL_ERROR:
299             errmsg = "internal error";
300             break;
301         case XML_ERR_PEREF_AT_EOF:
302             errmsg = "PEReference at end of document\n";
303             break;
304         case XML_ERR_PEREF_IN_PROLOG:
305             errmsg = "PEReference in prolog\n";
306             break;
307         case XML_ERR_PEREF_IN_EPILOG:
308             errmsg = "PEReference in epilog\n";
309             break;
310         case XML_ERR_PEREF_NO_NAME:
311             errmsg = "PEReference: no name\n";
312             break;
313         case XML_ERR_PEREF_SEMICOL_MISSING:
314             errmsg = "PEReference: expecting ';'\n";
315             break;
316         case XML_ERR_ENTITY_LOOP:
317             errmsg = "Detected an entity reference loop\n";
318             break;
319         case XML_ERR_ENTITY_NOT_STARTED:
320             errmsg = "EntityValue: \" or ' expected\n";
321             break;
322         case XML_ERR_ENTITY_PE_INTERNAL:
323             errmsg = "PEReferences forbidden in internal subset\n";
324             break;
325         case XML_ERR_ENTITY_NOT_FINISHED:
326             errmsg = "EntityValue: \" or ' expected\n";
327             break;
328         case XML_ERR_ATTRIBUTE_NOT_STARTED:
329             errmsg = "AttValue: \" or ' expected\n";
330             break;
331         case XML_ERR_LT_IN_ATTRIBUTE:
332             errmsg = "Unescaped '<' not allowed in attributes values\n";
333             break;
334         case XML_ERR_LITERAL_NOT_STARTED:
335             errmsg = "SystemLiteral \" or ' expected\n";
336             break;
337         case XML_ERR_LITERAL_NOT_FINISHED:
338             errmsg = "Unfinished System or Public ID \" or ' expected\n";
339             break;
340         case XML_ERR_MISPLACED_CDATA_END:
341             errmsg = "Sequence ']]>' not allowed in content\n";
342             break;
343         case XML_ERR_URI_REQUIRED:
344             errmsg = "SYSTEM or PUBLIC, the URI is missing\n";
345             break;
346         case XML_ERR_PUBID_REQUIRED:
347             errmsg = "PUBLIC, the Public Identifier is missing\n";
348             break;
349         case XML_ERR_HYPHEN_IN_COMMENT:
350             errmsg = "Comment must not contain '--' (double-hyphen)\n";
351             break;
352         case XML_ERR_PI_NOT_STARTED:
353             errmsg = "xmlParsePI : no target name\n";
354             break;
355         case XML_ERR_RESERVED_XML_NAME:
356             errmsg = "Invalid PI name\n";
357             break;
358         case XML_ERR_NOTATION_NOT_STARTED:
359             errmsg = "NOTATION: Name expected here\n";
360             break;
361         case XML_ERR_NOTATION_NOT_FINISHED:
362             errmsg = "'>' required to close NOTATION declaration\n";
363             break;
364         case XML_ERR_VALUE_REQUIRED:
365             errmsg = "Entity value required\n";
366             break;
367         case XML_ERR_URI_FRAGMENT:
368             errmsg = "Fragment not allowed";
369             break;
370         case XML_ERR_ATTLIST_NOT_STARTED:
371             errmsg = "'(' required to start ATTLIST enumeration\n";
372             break;
373         case XML_ERR_NMTOKEN_REQUIRED:
374             errmsg = "NmToken expected in ATTLIST enumeration\n";
375             break;
376         case XML_ERR_ATTLIST_NOT_FINISHED:
377             errmsg = "')' required to finish ATTLIST enumeration\n";
378             break;
379         case XML_ERR_MIXED_NOT_STARTED:
380             errmsg = "MixedContentDecl : '|' or ')*' expected\n";
381             break;
382         case XML_ERR_PCDATA_REQUIRED:
383             errmsg = "MixedContentDecl : '#PCDATA' expected\n";
384             break;
385         case XML_ERR_ELEMCONTENT_NOT_STARTED:
386             errmsg = "ContentDecl : Name or '(' expected\n";
387             break;
388         case XML_ERR_ELEMCONTENT_NOT_FINISHED:
389             errmsg = "ContentDecl : ',' '|' or ')' expected\n";
390             break;
391         case XML_ERR_PEREF_IN_INT_SUBSET:
392             errmsg =
393                 "PEReference: forbidden within markup decl in internal subset\n";
394             break;
395         case XML_ERR_GT_REQUIRED:
396             errmsg = "expected '>'\n";
397             break;
398         case XML_ERR_CONDSEC_INVALID:
399             errmsg = "XML conditional section '[' expected\n";
400             break;
401         case XML_ERR_EXT_SUBSET_NOT_FINISHED:
402             errmsg = "Content error in the external subset\n";
403             break;
404         case XML_ERR_CONDSEC_INVALID_KEYWORD:
405             errmsg =
406                 "conditional section INCLUDE or IGNORE keyword expected\n";
407             break;
408         case XML_ERR_CONDSEC_NOT_FINISHED:
409             errmsg = "XML conditional section not closed\n";
410             break;
411         case XML_ERR_XMLDECL_NOT_STARTED:
412             errmsg = "Text declaration '<?xml' required\n";
413             break;
414         case XML_ERR_XMLDECL_NOT_FINISHED:
415             errmsg = "parsing XML declaration: '?>' expected\n";
416             break;
417         case XML_ERR_EXT_ENTITY_STANDALONE:
418             errmsg = "external parsed entities cannot be standalone\n";
419             break;
420         case XML_ERR_ENTITYREF_SEMICOL_MISSING:
421             errmsg = "EntityRef: expecting ';'\n";
422             break;
423         case XML_ERR_DOCTYPE_NOT_FINISHED:
424             errmsg = "DOCTYPE improperly terminated\n";
425             break;
426         case XML_ERR_LTSLASH_REQUIRED:
427             errmsg = "EndTag: '</' not found\n";
428             break;
429         case XML_ERR_EQUAL_REQUIRED:
430             errmsg = "expected '='\n";
431             break;
432         case XML_ERR_STRING_NOT_CLOSED:
433             errmsg = "String not closed expecting \" or '\n";
434             break;
435         case XML_ERR_STRING_NOT_STARTED:
436             errmsg = "String not started expecting ' or \"\n";
437             break;
438         case XML_ERR_ENCODING_NAME:
439             errmsg = "Invalid XML encoding name\n";
440             break;
441         case XML_ERR_STANDALONE_VALUE:
442             errmsg = "standalone accepts only 'yes' or 'no'\n";
443             break;
444         case XML_ERR_DOCUMENT_EMPTY:
445             errmsg = "Document is empty\n";
446             break;
447         case XML_ERR_DOCUMENT_END:
448             errmsg = "Extra content at the end of the document\n";
449             break;
450         case XML_ERR_NOT_WELL_BALANCED:
451             errmsg = "chunk is not well balanced\n";
452             break;
453         case XML_ERR_EXTRA_CONTENT:
454             errmsg = "extra content at the end of well balanced chunk\n";
455             break;
456         case XML_ERR_VERSION_MISSING:
457             errmsg = "Malformed declaration expecting version\n";
458             break;
459 #if 0
460         case:
461             errmsg = "\n";
462             break;
463 #endif
464         default:
465             errmsg = "Unregistered error message\n";
466     }
467     if (ctxt != NULL)
468         ctxt->errNo = error;
469     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
470                     XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, errmsg,
471                     info);
472     if (ctxt != NULL) {
473         ctxt->wellFormed = 0;
474         if (ctxt->recovery == 0)
475             ctxt->disableSAX = 1;
476     }
477 }
478
479 /**
480  * xmlFatalErrMsg:
481  * @ctxt:  an XML parser context
482  * @error:  the error number
483  * @msg:  the error message
484  *
485  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
486  */
487 static void
488 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
489                const char *msg)
490 {
491     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
492         (ctxt->instate == XML_PARSER_EOF))
493         return;
494     if (ctxt != NULL)
495         ctxt->errNo = error;
496     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
497                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
498     if (ctxt != NULL) {
499         ctxt->wellFormed = 0;
500         if (ctxt->recovery == 0)
501             ctxt->disableSAX = 1;
502     }
503 }
504
505 /**
506  * xmlWarningMsg:
507  * @ctxt:  an XML parser context
508  * @error:  the error number
509  * @msg:  the error message
510  * @str1:  extra data
511  * @str2:  extra data
512  *
513  * Handle a warning.
514  */
515 static void
516 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
517               const char *msg, const xmlChar *str1, const xmlChar *str2)
518 {
519     xmlStructuredErrorFunc schannel = NULL;
520
521     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
522         (ctxt->instate == XML_PARSER_EOF))
523         return;
524     if ((ctxt != NULL) && (ctxt->sax != NULL) &&
525         (ctxt->sax->initialized == XML_SAX2_MAGIC))
526         schannel = ctxt->sax->serror;
527     if (ctxt != NULL) {
528         __xmlRaiseError(schannel,
529                     (ctxt->sax) ? ctxt->sax->warning : NULL,
530                     ctxt->userData,
531                     ctxt, NULL, XML_FROM_PARSER, error,
532                     XML_ERR_WARNING, NULL, 0,
533                     (const char *) str1, (const char *) str2, NULL, 0, 0,
534                     msg, (const char *) str1, (const char *) str2);
535     } else {
536         __xmlRaiseError(schannel, NULL, NULL,
537                     ctxt, NULL, XML_FROM_PARSER, error,
538                     XML_ERR_WARNING, NULL, 0,
539                     (const char *) str1, (const char *) str2, NULL, 0, 0,
540                     msg, (const char *) str1, (const char *) str2);
541     }
542 }
543
544 /**
545  * xmlValidityError:
546  * @ctxt:  an XML parser context
547  * @error:  the error number
548  * @msg:  the error message
549  * @str1:  extra data
550  *
551  * Handle a validity error.
552  */
553 static void
554 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
555               const char *msg, const xmlChar *str1, const xmlChar *str2)
556 {
557     xmlStructuredErrorFunc schannel = NULL;
558
559     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
560         (ctxt->instate == XML_PARSER_EOF))
561         return;
562     if (ctxt != NULL) {
563         ctxt->errNo = error;
564         if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
565             schannel = ctxt->sax->serror;
566     }
567     if (ctxt != NULL) {
568         __xmlRaiseError(schannel,
569                     ctxt->vctxt.error, ctxt->vctxt.userData,
570                     ctxt, NULL, XML_FROM_DTD, error,
571                     XML_ERR_ERROR, NULL, 0, (const char *) str1,
572                     (const char *) str2, NULL, 0, 0,
573                     msg, (const char *) str1, (const char *) str2);
574         ctxt->valid = 0;
575     } else {
576         __xmlRaiseError(schannel, NULL, NULL,
577                     ctxt, NULL, XML_FROM_DTD, error,
578                     XML_ERR_ERROR, NULL, 0, (const char *) str1,
579                     (const char *) str2, NULL, 0, 0,
580                     msg, (const char *) str1, (const char *) str2);
581     }
582 }
583
584 /**
585  * xmlFatalErrMsgInt:
586  * @ctxt:  an XML parser context
587  * @error:  the error number
588  * @msg:  the error message
589  * @val:  an integer value
590  *
591  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
592  */
593 static void
594 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
595                   const char *msg, int val)
596 {
597     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
598         (ctxt->instate == XML_PARSER_EOF))
599         return;
600     if (ctxt != NULL)
601         ctxt->errNo = error;
602     __xmlRaiseError(NULL, NULL, NULL,
603                     ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
604                     NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
605     if (ctxt != NULL) {
606         ctxt->wellFormed = 0;
607         if (ctxt->recovery == 0)
608             ctxt->disableSAX = 1;
609     }
610 }
611
612 /**
613  * xmlFatalErrMsgStrIntStr:
614  * @ctxt:  an XML parser context
615  * @error:  the error number
616  * @msg:  the error message
617  * @str1:  an string info
618  * @val:  an integer value
619  * @str2:  an string info
620  *
621  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
622  */
623 static void
624 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
625                   const char *msg, const xmlChar *str1, int val, 
626                   const xmlChar *str2)
627 {
628     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
629         (ctxt->instate == XML_PARSER_EOF))
630         return;
631     if (ctxt != NULL)
632         ctxt->errNo = error;
633     __xmlRaiseError(NULL, NULL, NULL,
634                     ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
635                     NULL, 0, (const char *) str1, (const char *) str2,
636                     NULL, val, 0, msg, str1, val, str2);
637     if (ctxt != NULL) {
638         ctxt->wellFormed = 0;
639         if (ctxt->recovery == 0)
640             ctxt->disableSAX = 1;
641     }
642 }
643
644 /**
645  * xmlFatalErrMsgStr:
646  * @ctxt:  an XML parser context
647  * @error:  the error number
648  * @msg:  the error message
649  * @val:  a string value
650  *
651  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
652  */
653 static void
654 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
655                   const char *msg, const xmlChar * val)
656 {
657     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
658         (ctxt->instate == XML_PARSER_EOF))
659         return;
660     if (ctxt != NULL)
661         ctxt->errNo = error;
662     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
663                     XML_FROM_PARSER, error, XML_ERR_FATAL,
664                     NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
665                     val);
666     if (ctxt != NULL) {
667         ctxt->wellFormed = 0;
668         if (ctxt->recovery == 0)
669             ctxt->disableSAX = 1;
670     }
671 }
672
673 /**
674  * xmlErrMsgStr:
675  * @ctxt:  an XML parser context
676  * @error:  the error number
677  * @msg:  the error message
678  * @val:  a string value
679  *
680  * Handle a non fatal parser error
681  */
682 static void
683 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
684                   const char *msg, const xmlChar * val)
685 {
686     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
687         (ctxt->instate == XML_PARSER_EOF))
688         return;
689     if (ctxt != NULL)
690         ctxt->errNo = error;
691     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
692                     XML_FROM_PARSER, error, XML_ERR_ERROR,
693                     NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
694                     val);
695 }
696
697 /**
698  * xmlNsErr:
699  * @ctxt:  an XML parser context
700  * @error:  the error number
701  * @msg:  the message
702  * @info1:  extra information string
703  * @info2:  extra information string
704  *
705  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
706  */
707 static void
708 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
709          const char *msg,
710          const xmlChar * info1, const xmlChar * info2,
711          const xmlChar * info3)
712 {
713     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
714         (ctxt->instate == XML_PARSER_EOF))
715         return;
716     if (ctxt != NULL)
717         ctxt->errNo = error;
718     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
719                     XML_ERR_ERROR, NULL, 0, (const char *) info1,
720                     (const char *) info2, (const char *) info3, 0, 0, msg,
721                     info1, info2, info3);
722     if (ctxt != NULL)
723         ctxt->nsWellFormed = 0;
724 }
725
726 /**
727  * xmlNsWarn
728  * @ctxt:  an XML parser context
729  * @error:  the error number
730  * @msg:  the message
731  * @info1:  extra information string
732  * @info2:  extra information string
733  *
734  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
735  */
736 static void
737 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
738          const char *msg,
739          const xmlChar * info1, const xmlChar * info2,
740          const xmlChar * info3)
741 {
742     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
743         (ctxt->instate == XML_PARSER_EOF))
744         return;
745     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
746                     XML_ERR_WARNING, NULL, 0, (const char *) info1,
747                     (const char *) info2, (const char *) info3, 0, 0, msg,
748                     info1, info2, info3);
749 }
750
751 /************************************************************************
752  *                                                                      *
753  *              Library wide options                                    *
754  *                                                                      *
755  ************************************************************************/
756
757 /**
758   * xmlHasFeature:
759   * @feature: the feature to be examined
760   *
761   * Examines if the library has been compiled with a given feature.
762   *
763   * Returns a non-zero value if the feature exist, otherwise zero.
764   * Returns zero (0) if the feature does not exist or an unknown
765   * unknown feature is requested, non-zero otherwise.
766   */
767 int
768 xmlHasFeature(xmlFeature feature)
769 {
770     switch (feature) {
771         case XML_WITH_THREAD:
772 #ifdef LIBXML_THREAD_ENABLED
773             return(1);
774 #else
775             return(0);
776 #endif
777         case XML_WITH_TREE:
778 #ifdef LIBXML_TREE_ENABLED
779             return(1);
780 #else
781             return(0);
782 #endif
783         case XML_WITH_OUTPUT:
784 #ifdef LIBXML_OUTPUT_ENABLED
785             return(1);
786 #else
787             return(0);
788 #endif
789         case XML_WITH_PUSH:
790 #ifdef LIBXML_PUSH_ENABLED
791             return(1);
792 #else
793             return(0);
794 #endif
795         case XML_WITH_READER:
796 #ifdef LIBXML_READER_ENABLED
797             return(1);
798 #else
799             return(0);
800 #endif
801         case XML_WITH_PATTERN:
802 #ifdef LIBXML_PATTERN_ENABLED
803             return(1);
804 #else
805             return(0);
806 #endif
807         case XML_WITH_WRITER:
808 #ifdef LIBXML_WRITER_ENABLED
809             return(1);
810 #else
811             return(0);
812 #endif
813         case XML_WITH_SAX1:
814 #ifdef LIBXML_SAX1_ENABLED
815             return(1);
816 #else
817             return(0);
818 #endif
819         case XML_WITH_FTP:
820 #ifdef LIBXML_FTP_ENABLED
821             return(1);
822 #else
823             return(0);
824 #endif
825         case XML_WITH_HTTP:
826 #ifdef LIBXML_HTTP_ENABLED
827             return(1);
828 #else
829             return(0);
830 #endif
831         case XML_WITH_VALID:
832 #ifdef LIBXML_VALID_ENABLED
833             return(1);
834 #else
835             return(0);
836 #endif
837         case XML_WITH_HTML:
838 #ifdef LIBXML_HTML_ENABLED
839             return(1);
840 #else
841             return(0);
842 #endif
843         case XML_WITH_LEGACY:
844 #ifdef LIBXML_LEGACY_ENABLED
845             return(1);
846 #else
847             return(0);
848 #endif
849         case XML_WITH_C14N:
850 #ifdef LIBXML_C14N_ENABLED
851             return(1);
852 #else
853             return(0);
854 #endif
855         case XML_WITH_CATALOG:
856 #ifdef LIBXML_CATALOG_ENABLED
857             return(1);
858 #else
859             return(0);
860 #endif
861         case XML_WITH_XPATH:
862 #ifdef LIBXML_XPATH_ENABLED
863             return(1);
864 #else
865             return(0);
866 #endif
867         case XML_WITH_XPTR:
868 #ifdef LIBXML_XPTR_ENABLED
869             return(1);
870 #else
871             return(0);
872 #endif
873         case XML_WITH_XINCLUDE:
874 #ifdef LIBXML_XINCLUDE_ENABLED
875             return(1);
876 #else
877             return(0);
878 #endif
879         case XML_WITH_ICONV:
880 #ifdef LIBXML_ICONV_ENABLED
881             return(1);
882 #else
883             return(0);
884 #endif
885         case XML_WITH_ISO8859X:
886 #ifdef LIBXML_ISO8859X_ENABLED
887             return(1);
888 #else
889             return(0);
890 #endif
891         case XML_WITH_UNICODE:
892 #ifdef LIBXML_UNICODE_ENABLED
893             return(1);
894 #else
895             return(0);
896 #endif
897         case XML_WITH_REGEXP:
898 #ifdef LIBXML_REGEXP_ENABLED
899             return(1);
900 #else
901             return(0);
902 #endif
903         case XML_WITH_AUTOMATA:
904 #ifdef LIBXML_AUTOMATA_ENABLED
905             return(1);
906 #else
907             return(0);
908 #endif
909         case XML_WITH_EXPR:
910 #ifdef LIBXML_EXPR_ENABLED
911             return(1);
912 #else
913             return(0);
914 #endif
915         case XML_WITH_SCHEMAS:
916 #ifdef LIBXML_SCHEMAS_ENABLED
917             return(1);
918 #else
919             return(0);
920 #endif
921         case XML_WITH_SCHEMATRON:
922 #ifdef LIBXML_SCHEMATRON_ENABLED
923             return(1);
924 #else
925             return(0);
926 #endif
927         case XML_WITH_MODULES:
928 #ifdef LIBXML_MODULES_ENABLED
929             return(1);
930 #else
931             return(0);
932 #endif
933         case XML_WITH_DEBUG:
934 #ifdef LIBXML_DEBUG_ENABLED
935             return(1);
936 #else
937             return(0);
938 #endif
939         case XML_WITH_DEBUG_MEM:
940 #ifdef DEBUG_MEMORY_LOCATION
941             return(1);
942 #else
943             return(0);
944 #endif
945         case XML_WITH_DEBUG_RUN:
946 #ifdef LIBXML_DEBUG_RUNTIME
947             return(1);
948 #else
949             return(0);
950 #endif
951         case XML_WITH_ZLIB:
952 #ifdef LIBXML_ZLIB_ENABLED
953             return(1);
954 #else
955             return(0);
956 #endif
957         case XML_WITH_ICU:
958 #ifdef LIBXML_ICU_ENABLED
959             return(1);
960 #else
961             return(0);
962 #endif
963         default:
964             break;
965      }
966      return(0);
967 }
968
969 /************************************************************************
970  *                                                                      *
971  *              SAX2 defaulted attributes handling                      *
972  *                                                                      *
973  ************************************************************************/
974
975 /**
976  * xmlDetectSAX2:
977  * @ctxt:  an XML parser context
978  *
979  * Do the SAX2 detection and specific intialization
980  */
981 static void
982 xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
983     if (ctxt == NULL) return;
984 #ifdef LIBXML_SAX1_ENABLED
985     if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
986         ((ctxt->sax->startElementNs != NULL) ||
987          (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
988 #else
989     ctxt->sax2 = 1;
990 #endif /* LIBXML_SAX1_ENABLED */
991
992     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
993     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
994     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
995     if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || 
996                 (ctxt->str_xml_ns == NULL)) {
997         xmlErrMemory(ctxt, NULL);
998     }
999 }
1000
1001 typedef struct _xmlDefAttrs xmlDefAttrs;
1002 typedef xmlDefAttrs *xmlDefAttrsPtr;
1003 struct _xmlDefAttrs {
1004     int nbAttrs;        /* number of defaulted attributes on that element */
1005     int maxAttrs;       /* the size of the array */
1006     const xmlChar *values[5]; /* array of localname/prefix/values/external */
1007 };
1008
1009 /**
1010  * xmlAttrNormalizeSpace:
1011  * @src: the source string
1012  * @dst: the target string
1013  *
1014  * Normalize the space in non CDATA attribute values:
1015  * If the attribute type is not CDATA, then the XML processor MUST further
1016  * process the normalized attribute value by discarding any leading and
1017  * trailing space (#x20) characters, and by replacing sequences of space
1018  * (#x20) characters by a single space (#x20) character.
1019  * Note that the size of dst need to be at least src, and if one doesn't need
1020  * to preserve dst (and it doesn't come from a dictionary or read-only) then
1021  * passing src as dst is just fine.
1022  *
1023  * Returns a pointer to the normalized value (dst) or NULL if no conversion
1024  *         is needed.
1025  */
1026 static xmlChar *
1027 xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1028 {
1029     if ((src == NULL) || (dst == NULL))
1030         return(NULL);
1031
1032     while (*src == 0x20) src++;
1033     while (*src != 0) {
1034         if (*src == 0x20) {
1035             while (*src == 0x20) src++;
1036             if (*src != 0)
1037                 *dst++ = 0x20;
1038         } else {
1039             *dst++ = *src++;
1040         }
1041     }
1042     *dst = 0;
1043     if (dst == src)
1044        return(NULL);
1045     return(dst);
1046 }
1047
1048 /**
1049  * xmlAttrNormalizeSpace2:
1050  * @src: the source string
1051  *
1052  * Normalize the space in non CDATA attribute values, a slightly more complex
1053  * front end to avoid allocation problems when running on attribute values
1054  * coming from the input.
1055  *
1056  * Returns a pointer to the normalized value (dst) or NULL if no conversion
1057  *         is needed.
1058  */
1059 static const xmlChar *
1060 xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1061 {
1062     int i;
1063     int remove_head = 0;
1064     int need_realloc = 0;
1065     const xmlChar *cur;
1066
1067     if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1068         return(NULL);
1069     i = *len;
1070     if (i <= 0)
1071         return(NULL);
1072
1073     cur = src;
1074     while (*cur == 0x20) {
1075         cur++;
1076         remove_head++;
1077     }
1078     while (*cur != 0) {
1079         if (*cur == 0x20) {
1080             cur++;
1081             if ((*cur == 0x20) || (*cur == 0)) {
1082                 need_realloc = 1;
1083                 break;
1084             }
1085         } else
1086             cur++;
1087     }
1088     if (need_realloc) {
1089         xmlChar *ret;
1090
1091         ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1092         if (ret == NULL) {
1093             xmlErrMemory(ctxt, NULL);
1094             return(NULL);
1095         }
1096         xmlAttrNormalizeSpace(ret, ret);
1097         *len = (int) strlen((const char *)ret);
1098         return(ret);
1099     } else if (remove_head) {
1100         *len -= remove_head;
1101         memmove(src, src + remove_head, 1 + *len);
1102         return(src);
1103     }
1104     return(NULL);
1105 }
1106
1107 /**
1108  * xmlAddDefAttrs:
1109  * @ctxt:  an XML parser context
1110  * @fullname:  the element fullname
1111  * @fullattr:  the attribute fullname
1112  * @value:  the attribute value
1113  *
1114  * Add a defaulted attribute for an element
1115  */
1116 static void
1117 xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1118                const xmlChar *fullname,
1119                const xmlChar *fullattr,
1120                const xmlChar *value) {
1121     xmlDefAttrsPtr defaults;
1122     int len;
1123     const xmlChar *name;
1124     const xmlChar *prefix;
1125
1126     /*
1127      * Allows to detect attribute redefinitions
1128      */
1129     if (ctxt->attsSpecial != NULL) {
1130         if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1131             return;
1132     }
1133
1134     if (ctxt->attsDefault == NULL) {
1135         ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1136         if (ctxt->attsDefault == NULL)
1137             goto mem_error;
1138     }
1139
1140     /*
1141      * split the element name into prefix:localname , the string found
1142      * are within the DTD and then not associated to namespace names.
1143      */
1144     name = xmlSplitQName3(fullname, &len);
1145     if (name == NULL) {
1146         name = xmlDictLookup(ctxt->dict, fullname, -1);
1147         prefix = NULL;
1148     } else {
1149         name = xmlDictLookup(ctxt->dict, name, -1);
1150         prefix = xmlDictLookup(ctxt->dict, fullname, len);
1151     }
1152
1153     /*
1154      * make sure there is some storage
1155      */
1156     defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1157     if (defaults == NULL) {
1158         defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1159                            (4 * 5) * sizeof(const xmlChar *));
1160         if (defaults == NULL)
1161             goto mem_error;
1162         defaults->nbAttrs = 0;
1163         defaults->maxAttrs = 4;
1164         if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1165                                 defaults, NULL) < 0) {
1166             xmlFree(defaults);
1167             goto mem_error;
1168         }
1169     } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1170         xmlDefAttrsPtr temp;
1171
1172         temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1173                        (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1174         if (temp == NULL)
1175             goto mem_error;
1176         defaults = temp;
1177         defaults->maxAttrs *= 2;
1178         if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1179                                 defaults, NULL) < 0) {
1180             xmlFree(defaults);
1181             goto mem_error;
1182         }
1183     }
1184
1185     /*
1186      * Split the element name into prefix:localname , the string found
1187      * are within the DTD and hen not associated to namespace names.
1188      */
1189     name = xmlSplitQName3(fullattr, &len);
1190     if (name == NULL) {
1191         name = xmlDictLookup(ctxt->dict, fullattr, -1);
1192         prefix = NULL;
1193     } else {
1194         name = xmlDictLookup(ctxt->dict, name, -1);
1195         prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1196     }
1197
1198     defaults->values[5 * defaults->nbAttrs] = name;
1199     defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1200     /* intern the string and precompute the end */
1201     len = xmlStrlen(value);
1202     value = xmlDictLookup(ctxt->dict, value, len);
1203     defaults->values[5 * defaults->nbAttrs + 2] = value;
1204     defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1205     if (ctxt->external)
1206         defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1207     else
1208         defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1209     defaults->nbAttrs++;
1210
1211     return;
1212
1213 mem_error:
1214     xmlErrMemory(ctxt, NULL);
1215     return;
1216 }
1217
1218 /**
1219  * xmlAddSpecialAttr:
1220  * @ctxt:  an XML parser context
1221  * @fullname:  the element fullname
1222  * @fullattr:  the attribute fullname
1223  * @type:  the attribute type
1224  *
1225  * Register this attribute type
1226  */
1227 static void
1228 xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1229                   const xmlChar *fullname,
1230                   const xmlChar *fullattr,
1231                   int type)
1232 {
1233     if (ctxt->attsSpecial == NULL) {
1234         ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1235         if (ctxt->attsSpecial == NULL)
1236             goto mem_error;
1237     }
1238
1239     if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1240         return;
1241
1242     xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1243                      (void *) (long) type);
1244     return;
1245
1246 mem_error:
1247     xmlErrMemory(ctxt, NULL);
1248     return;
1249 }
1250
1251 /**
1252  * xmlCleanSpecialAttrCallback:
1253  *
1254  * Removes CDATA attributes from the special attribute table
1255  */
1256 static void
1257 xmlCleanSpecialAttrCallback(void *payload, void *data,
1258                             const xmlChar *fullname, const xmlChar *fullattr,
1259                             const xmlChar *unused ATTRIBUTE_UNUSED) {
1260     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1261
1262     if (((long) payload) == XML_ATTRIBUTE_CDATA) {
1263         xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1264     }
1265 }
1266
1267 /**
1268  * xmlCleanSpecialAttr:
1269  * @ctxt:  an XML parser context
1270  *
1271  * Trim the list of attributes defined to remove all those of type
1272  * CDATA as they are not special. This call should be done when finishing
1273  * to parse the DTD and before starting to parse the document root.
1274  */
1275 static void
1276 xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1277 {
1278     if (ctxt->attsSpecial == NULL)
1279         return;
1280
1281     xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1282
1283     if (xmlHashSize(ctxt->attsSpecial) == 0) {
1284         xmlHashFree(ctxt->attsSpecial, NULL);
1285         ctxt->attsSpecial = NULL;
1286     }
1287     return;
1288 }
1289
1290 /**
1291  * xmlCheckLanguageID:
1292  * @lang:  pointer to the string value
1293  *
1294  * Checks that the value conforms to the LanguageID production:
1295  *
1296  * NOTE: this is somewhat deprecated, those productions were removed from
1297  *       the XML Second edition.
1298  *
1299  * [33] LanguageID ::= Langcode ('-' Subcode)*
1300  * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1301  * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1302  * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1303  * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1304  * [38] Subcode ::= ([a-z] | [A-Z])+
1305  *
1306  * The current REC reference the sucessors of RFC 1766, currently 5646
1307  *
1308  * http://www.rfc-editor.org/rfc/rfc5646.txt
1309  * langtag       = language
1310  *                 ["-" script]
1311  *                 ["-" region]
1312  *                 *("-" variant)
1313  *                 *("-" extension)
1314  *                 ["-" privateuse]
1315  * language      = 2*3ALPHA            ; shortest ISO 639 code
1316  *                 ["-" extlang]       ; sometimes followed by
1317  *                                     ; extended language subtags
1318  *               / 4ALPHA              ; or reserved for future use
1319  *               / 5*8ALPHA            ; or registered language subtag
1320  *
1321  * extlang       = 3ALPHA              ; selected ISO 639 codes
1322  *                 *2("-" 3ALPHA)      ; permanently reserved
1323  *
1324  * script        = 4ALPHA              ; ISO 15924 code
1325  *
1326  * region        = 2ALPHA              ; ISO 3166-1 code
1327  *               / 3DIGIT              ; UN M.49 code
1328  *
1329  * variant       = 5*8alphanum         ; registered variants
1330  *               / (DIGIT 3alphanum)
1331  *
1332  * extension     = singleton 1*("-" (2*8alphanum))
1333  *
1334  *                                     ; Single alphanumerics
1335  *                                     ; "x" reserved for private use
1336  * singleton     = DIGIT               ; 0 - 9
1337  *               / %x41-57             ; A - W
1338  *               / %x59-5A             ; Y - Z
1339  *               / %x61-77             ; a - w
1340  *               / %x79-7A             ; y - z
1341  *
1342  * it sounds right to still allow Irregular i-xxx IANA and user codes too
1343  * The parser below doesn't try to cope with extension or privateuse
1344  * that could be added but that's not interoperable anyway
1345  *
1346  * Returns 1 if correct 0 otherwise
1347  **/
1348 int
1349 xmlCheckLanguageID(const xmlChar * lang)
1350 {
1351     const xmlChar *cur = lang, *nxt;
1352
1353     if (cur == NULL)
1354         return (0);
1355     if (((cur[0] == 'i') && (cur[1] == '-')) ||
1356         ((cur[0] == 'I') && (cur[1] == '-')) ||
1357         ((cur[0] == 'x') && (cur[1] == '-')) ||
1358         ((cur[0] == 'X') && (cur[1] == '-'))) {
1359         /*
1360          * Still allow IANA code and user code which were coming
1361          * from the previous version of the XML-1.0 specification
1362          * it's deprecated but we should not fail
1363          */
1364         cur += 2;
1365         while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1366                ((cur[0] >= 'a') && (cur[0] <= 'z')))
1367             cur++;
1368         return(cur[0] == 0);
1369     }
1370     nxt = cur;
1371     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1372            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1373            nxt++;
1374     if (nxt - cur >= 4) {
1375         /*
1376          * Reserved
1377          */
1378         if ((nxt - cur > 8) || (nxt[0] != 0))
1379             return(0);
1380         return(1);
1381     }
1382     if (nxt - cur < 2)
1383         return(0);
1384     /* we got an ISO 639 code */
1385     if (nxt[0] == 0)
1386         return(1);
1387     if (nxt[0] != '-')
1388         return(0);
1389
1390     nxt++;
1391     cur = nxt;
1392     /* now we can have extlang or script or region or variant */
1393     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1394         goto region_m49;
1395
1396     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1397            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1398            nxt++;
1399     if (nxt - cur == 4)
1400         goto script;
1401     if (nxt - cur == 2)
1402         goto region;
1403     if ((nxt - cur >= 5) && (nxt - cur <= 8))
1404         goto variant;
1405     if (nxt - cur != 3)
1406         return(0);
1407     /* we parsed an extlang */
1408     if (nxt[0] == 0)
1409         return(1);
1410     if (nxt[0] != '-')
1411         return(0);
1412
1413     nxt++;
1414     cur = nxt;
1415     /* now we can have script or region or variant */
1416     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1417         goto region_m49;
1418
1419     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1420            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1421            nxt++;
1422     if (nxt - cur == 2)
1423         goto region;
1424     if ((nxt - cur >= 5) && (nxt - cur <= 8))
1425         goto variant;
1426     if (nxt - cur != 4)
1427         return(0);
1428     /* we parsed a script */
1429 script:
1430     if (nxt[0] == 0)
1431         return(1);
1432     if (nxt[0] != '-')
1433         return(0);
1434
1435     nxt++;
1436     cur = nxt;
1437     /* now we can have region or variant */
1438     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1439         goto region_m49;
1440
1441     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1442            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1443            nxt++;
1444
1445     if ((nxt - cur >= 5) && (nxt - cur <= 8))
1446         goto variant;
1447     if (nxt - cur != 2)
1448         return(0);
1449     /* we parsed a region */
1450 region:
1451     if (nxt[0] == 0)
1452         return(1);
1453     if (nxt[0] != '-')
1454         return(0);
1455
1456     nxt++;
1457     cur = nxt;
1458     /* now we can just have a variant */
1459     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1460            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1461            nxt++;
1462
1463     if ((nxt - cur < 5) || (nxt - cur > 8))
1464         return(0);
1465
1466     /* we parsed a variant */
1467 variant:
1468     if (nxt[0] == 0)
1469         return(1);
1470     if (nxt[0] != '-')
1471         return(0);
1472     /* extensions and private use subtags not checked */
1473     return (1);
1474
1475 region_m49:
1476     if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1477         ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1478         nxt += 3;
1479         goto region;
1480     }
1481     return(0);
1482 }
1483
1484 /************************************************************************
1485  *                                                                      *
1486  *              Parser stacks related functions and macros              *
1487  *                                                                      *
1488  ************************************************************************/
1489
1490 static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1491                                             const xmlChar ** str);
1492
1493 #ifdef SAX2
1494 /**
1495  * nsPush:
1496  * @ctxt:  an XML parser context
1497  * @prefix:  the namespace prefix or NULL
1498  * @URL:  the namespace name
1499  *
1500  * Pushes a new parser namespace on top of the ns stack
1501  *
1502  * Returns -1 in case of error, -2 if the namespace should be discarded
1503  *         and the index in the stack otherwise.
1504  */
1505 static int
1506 nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1507 {
1508     if (ctxt->options & XML_PARSE_NSCLEAN) {
1509         int i;
1510         for (i = 0;i < ctxt->nsNr;i += 2) {
1511             if (ctxt->nsTab[i] == prefix) {
1512                 /* in scope */
1513                 if (ctxt->nsTab[i + 1] == URL)
1514                     return(-2);
1515                 /* out of scope keep it */
1516                 break;
1517             }
1518         }
1519     }
1520     if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1521         ctxt->nsMax = 10;
1522         ctxt->nsNr = 0;
1523         ctxt->nsTab = (const xmlChar **)
1524                       xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1525         if (ctxt->nsTab == NULL) {
1526             xmlErrMemory(ctxt, NULL);
1527             ctxt->nsMax = 0;
1528             return (-1);
1529         }
1530     } else if (ctxt->nsNr >= ctxt->nsMax) {
1531         const xmlChar ** tmp;
1532         ctxt->nsMax *= 2;
1533         tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1534                                     ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1535         if (tmp == NULL) {
1536             xmlErrMemory(ctxt, NULL);
1537             ctxt->nsMax /= 2;
1538             return (-1);
1539         }
1540         ctxt->nsTab = tmp;
1541     }
1542     ctxt->nsTab[ctxt->nsNr++] = prefix;
1543     ctxt->nsTab[ctxt->nsNr++] = URL;
1544     return (ctxt->nsNr);
1545 }
1546 /**
1547  * nsPop:
1548  * @ctxt: an XML parser context
1549  * @nr:  the number to pop
1550  *
1551  * Pops the top @nr parser prefix/namespace from the ns stack
1552  *
1553  * Returns the number of namespaces removed
1554  */
1555 static int
1556 nsPop(xmlParserCtxtPtr ctxt, int nr)
1557 {
1558     int i;
1559
1560     if (ctxt->nsTab == NULL) return(0);
1561     if (ctxt->nsNr < nr) {
1562         xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1563         nr = ctxt->nsNr;
1564     }
1565     if (ctxt->nsNr <= 0)
1566         return (0);
1567
1568     for (i = 0;i < nr;i++) {
1569          ctxt->nsNr--;
1570          ctxt->nsTab[ctxt->nsNr] = NULL;
1571     }
1572     return(nr);
1573 }
1574 #endif
1575
1576 static int
1577 xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1578     const xmlChar **atts;
1579     int *attallocs;
1580     int maxatts;
1581
1582     if (ctxt->atts == NULL) {
1583         maxatts = 55; /* allow for 10 attrs by default */
1584         atts = (const xmlChar **)
1585                xmlMalloc(maxatts * sizeof(xmlChar *));
1586         if (atts == NULL) goto mem_error;
1587         ctxt->atts = atts;
1588         attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1589         if (attallocs == NULL) goto mem_error;
1590         ctxt->attallocs = attallocs;
1591         ctxt->maxatts = maxatts;
1592     } else if (nr + 5 > ctxt->maxatts) {
1593         maxatts = (nr + 5) * 2;
1594         atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1595                                      maxatts * sizeof(const xmlChar *));
1596         if (atts == NULL) goto mem_error;
1597         ctxt->atts = atts;
1598         attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1599                                      (maxatts / 5) * sizeof(int));
1600         if (attallocs == NULL) goto mem_error;
1601         ctxt->attallocs = attallocs;
1602         ctxt->maxatts = maxatts;
1603     }
1604     return(ctxt->maxatts);
1605 mem_error:
1606     xmlErrMemory(ctxt, NULL);
1607     return(-1);
1608 }
1609
1610 /**
1611  * inputPush:
1612  * @ctxt:  an XML parser context
1613  * @value:  the parser input
1614  *
1615  * Pushes a new parser input on top of the input stack
1616  *
1617  * Returns -1 in case of error, the index in the stack otherwise
1618  */
1619 int
1620 inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1621 {
1622     if ((ctxt == NULL) || (value == NULL))
1623         return(-1);
1624     if (ctxt->inputNr >= ctxt->inputMax) {
1625         ctxt->inputMax *= 2;
1626         ctxt->inputTab =
1627             (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1628                                              ctxt->inputMax *
1629                                              sizeof(ctxt->inputTab[0]));
1630         if (ctxt->inputTab == NULL) {
1631             xmlErrMemory(ctxt, NULL);
1632             xmlFreeInputStream(value);
1633             ctxt->inputMax /= 2;
1634             value = NULL;
1635             return (-1);
1636         }
1637     }
1638     ctxt->inputTab[ctxt->inputNr] = value;
1639     ctxt->input = value;
1640     return (ctxt->inputNr++);
1641 }
1642 /**
1643  * inputPop:
1644  * @ctxt: an XML parser context
1645  *
1646  * Pops the top parser input from the input stack
1647  *
1648  * Returns the input just removed
1649  */
1650 xmlParserInputPtr
1651 inputPop(xmlParserCtxtPtr ctxt)
1652 {
1653     xmlParserInputPtr ret;
1654
1655     if (ctxt == NULL)
1656         return(NULL);
1657     if (ctxt->inputNr <= 0)
1658         return (NULL);
1659     ctxt->inputNr--;
1660     if (ctxt->inputNr > 0)
1661         ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1662     else
1663         ctxt->input = NULL;
1664     ret = ctxt->inputTab[ctxt->inputNr];
1665     ctxt->inputTab[ctxt->inputNr] = NULL;
1666     return (ret);
1667 }
1668 /**
1669  * nodePush:
1670  * @ctxt:  an XML parser context
1671  * @value:  the element node
1672  *
1673  * Pushes a new element node on top of the node stack
1674  *
1675  * Returns -1 in case of error, the index in the stack otherwise
1676  */
1677 int
1678 nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1679 {
1680     if (ctxt == NULL) return(0);
1681     if (ctxt->nodeNr >= ctxt->nodeMax) {
1682         xmlNodePtr *tmp;
1683
1684         tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1685                                       ctxt->nodeMax * 2 *
1686                                       sizeof(ctxt->nodeTab[0]));
1687         if (tmp == NULL) {
1688             xmlErrMemory(ctxt, NULL);
1689             return (-1);
1690         }
1691         ctxt->nodeTab = tmp;
1692         ctxt->nodeMax *= 2;
1693     }
1694     if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1695         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1696         xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1697                  "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1698                           xmlParserMaxDepth);
1699         ctxt->instate = XML_PARSER_EOF;
1700         return(-1);
1701     }
1702     ctxt->nodeTab[ctxt->nodeNr] = value;
1703     ctxt->node = value;
1704     return (ctxt->nodeNr++);
1705 }
1706
1707 /**
1708  * nodePop:
1709  * @ctxt: an XML parser context
1710  *
1711  * Pops the top element node from the node stack
1712  *
1713  * Returns the node just removed
1714  */
1715 xmlNodePtr
1716 nodePop(xmlParserCtxtPtr ctxt)
1717 {
1718     xmlNodePtr ret;
1719
1720     if (ctxt == NULL) return(NULL);
1721     if (ctxt->nodeNr <= 0)
1722         return (NULL);
1723     ctxt->nodeNr--;
1724     if (ctxt->nodeNr > 0)
1725         ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1726     else
1727         ctxt->node = NULL;
1728     ret = ctxt->nodeTab[ctxt->nodeNr];
1729     ctxt->nodeTab[ctxt->nodeNr] = NULL;
1730     return (ret);
1731 }
1732
1733 #ifdef LIBXML_PUSH_ENABLED
1734 /**
1735  * nameNsPush:
1736  * @ctxt:  an XML parser context
1737  * @value:  the element name
1738  * @prefix:  the element prefix
1739  * @URI:  the element namespace name
1740  *
1741  * Pushes a new element name/prefix/URL on top of the name stack
1742  *
1743  * Returns -1 in case of error, the index in the stack otherwise
1744  */
1745 static int
1746 nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1747            const xmlChar *prefix, const xmlChar *URI, int nsNr)
1748 {
1749     if (ctxt->nameNr >= ctxt->nameMax) {
1750         const xmlChar * *tmp;
1751         void **tmp2;
1752         ctxt->nameMax *= 2;
1753         tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1754                                     ctxt->nameMax *
1755                                     sizeof(ctxt->nameTab[0]));
1756         if (tmp == NULL) {
1757             ctxt->nameMax /= 2;
1758             goto mem_error;
1759         }
1760         ctxt->nameTab = tmp;
1761         tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
1762                                     ctxt->nameMax * 3 *
1763                                     sizeof(ctxt->pushTab[0]));
1764         if (tmp2 == NULL) {
1765             ctxt->nameMax /= 2;
1766             goto mem_error;
1767         }
1768         ctxt->pushTab = tmp2;
1769     }
1770     ctxt->nameTab[ctxt->nameNr] = value;
1771     ctxt->name = value;
1772     ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
1773     ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
1774     ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
1775     return (ctxt->nameNr++);
1776 mem_error:
1777     xmlErrMemory(ctxt, NULL);
1778     return (-1);
1779 }
1780 /**
1781  * nameNsPop:
1782  * @ctxt: an XML parser context
1783  *
1784  * Pops the top element/prefix/URI name from the name stack
1785  *
1786  * Returns the name just removed
1787  */
1788 static const xmlChar *
1789 nameNsPop(xmlParserCtxtPtr ctxt)
1790 {
1791     const xmlChar *ret;
1792
1793     if (ctxt->nameNr <= 0)
1794         return (NULL);
1795     ctxt->nameNr--;
1796     if (ctxt->nameNr > 0)
1797         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1798     else
1799         ctxt->name = NULL;
1800     ret = ctxt->nameTab[ctxt->nameNr];
1801     ctxt->nameTab[ctxt->nameNr] = NULL;
1802     return (ret);
1803 }
1804 #endif /* LIBXML_PUSH_ENABLED */
1805
1806 /**
1807  * namePush:
1808  * @ctxt:  an XML parser context
1809  * @value:  the element name
1810  *
1811  * Pushes a new element name on top of the name stack
1812  *
1813  * Returns -1 in case of error, the index in the stack otherwise
1814  */
1815 int
1816 namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1817 {
1818     if (ctxt == NULL) return (-1);
1819
1820     if (ctxt->nameNr >= ctxt->nameMax) {
1821         const xmlChar * *tmp;
1822         ctxt->nameMax *= 2;
1823         tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1824                                     ctxt->nameMax *
1825                                     sizeof(ctxt->nameTab[0]));
1826         if (tmp == NULL) {
1827             ctxt->nameMax /= 2;
1828             goto mem_error;
1829         }
1830         ctxt->nameTab = tmp;
1831     }
1832     ctxt->nameTab[ctxt->nameNr] = value;
1833     ctxt->name = value;
1834     return (ctxt->nameNr++);
1835 mem_error:
1836     xmlErrMemory(ctxt, NULL);
1837     return (-1);
1838 }
1839 /**
1840  * namePop:
1841  * @ctxt: an XML parser context
1842  *
1843  * Pops the top element name from the name stack
1844  *
1845  * Returns the name just removed
1846  */
1847 const xmlChar *
1848 namePop(xmlParserCtxtPtr ctxt)
1849 {
1850     const xmlChar *ret;
1851
1852     if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1853         return (NULL);
1854     ctxt->nameNr--;
1855     if (ctxt->nameNr > 0)
1856         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1857     else
1858         ctxt->name = NULL;
1859     ret = ctxt->nameTab[ctxt->nameNr];
1860     ctxt->nameTab[ctxt->nameNr] = NULL;
1861     return (ret);
1862 }
1863
1864 static int spacePush(xmlParserCtxtPtr ctxt, int val) {
1865     if (ctxt->spaceNr >= ctxt->spaceMax) {
1866         int *tmp;
1867
1868         ctxt->spaceMax *= 2;
1869         tmp = (int *) xmlRealloc(ctxt->spaceTab,
1870                                  ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
1871         if (tmp == NULL) {
1872             xmlErrMemory(ctxt, NULL);
1873             ctxt->spaceMax /=2;
1874             return(-1);
1875         }
1876         ctxt->spaceTab = tmp;
1877     }
1878     ctxt->spaceTab[ctxt->spaceNr] = val;
1879     ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
1880     return(ctxt->spaceNr++);
1881 }
1882
1883 static int spacePop(xmlParserCtxtPtr ctxt) {
1884     int ret;
1885     if (ctxt->spaceNr <= 0) return(0);
1886     ctxt->spaceNr--;
1887     if (ctxt->spaceNr > 0)
1888         ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
1889     else
1890         ctxt->space = &ctxt->spaceTab[0];
1891     ret = ctxt->spaceTab[ctxt->spaceNr];
1892     ctxt->spaceTab[ctxt->spaceNr] = -1;
1893     return(ret);
1894 }
1895
1896 /*
1897  * Macros for accessing the content. Those should be used only by the parser,
1898  * and not exported.
1899  *
1900  * Dirty macros, i.e. one often need to make assumption on the context to
1901  * use them
1902  *
1903  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
1904  *           To be used with extreme caution since operations consuming
1905  *           characters may move the input buffer to a different location !
1906  *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
1907  *           This should be used internally by the parser
1908  *           only to compare to ASCII values otherwise it would break when
1909  *           running with UTF-8 encoding.
1910  *   RAW     same as CUR but in the input buffer, bypass any token
1911  *           extraction that may have been done
1912  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
1913  *           to compare on ASCII based substring.
1914  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1915  *           strings without newlines within the parser.
1916  *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII 
1917  *           defined char within the parser.
1918  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1919  *
1920  *   NEXT    Skip to the next character, this does the proper decoding
1921  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
1922  *   NEXTL(l) Skip the current unicode character of l xmlChars long.
1923  *   CUR_CHAR(l) returns the current unicode character (int), set l
1924  *           to the number of xmlChars used for the encoding [0-5].
1925  *   CUR_SCHAR  same but operate on a string instead of the context
1926  *   COPY_BUF  copy the current unicode char to the target buffer, increment
1927  *            the index
1928  *   GROW, SHRINK  handling of input buffers
1929  */
1930
1931 #define RAW (*ctxt->input->cur)
1932 #define CUR (*ctxt->input->cur)
1933 #define NXT(val) ctxt->input->cur[(val)]
1934 #define CUR_PTR ctxt->input->cur
1935
1936 #define CMP4( s, c1, c2, c3, c4 ) \
1937   ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
1938     ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
1939 #define CMP5( s, c1, c2, c3, c4, c5 ) \
1940   ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
1941 #define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
1942   ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
1943 #define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
1944   ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
1945 #define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
1946   ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
1947 #define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
1948   ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
1949     ((unsigned char *) s)[ 8 ] == c9 )
1950 #define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
1951   ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
1952     ((unsigned char *) s)[ 9 ] == c10 )
1953
1954 #define SKIP(val) do {                                                  \
1955     ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);                   \
1956     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
1957     if ((*ctxt->input->cur == 0) &&                                     \
1958         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
1959             xmlPopInput(ctxt);                                          \
1960   } while (0)
1961
1962 #define SKIPL(val) do {                                                 \
1963     int skipl;                                                          \
1964     for(skipl=0; skipl<val; skipl++) {                                  \
1965         if (*(ctxt->input->cur) == '\n') {                              \
1966         ctxt->input->line++; ctxt->input->col = 1;                      \
1967         } else ctxt->input->col++;                                      \
1968         ctxt->nbChars++;                                                \
1969         ctxt->input->cur++;                                             \
1970     }                                                                   \
1971     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
1972     if ((*ctxt->input->cur == 0) &&                                     \
1973         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
1974             xmlPopInput(ctxt);                                          \
1975   } while (0)
1976
1977 #define SHRINK if ((ctxt->progressive == 0) &&                          \
1978                    (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
1979                    (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
1980         xmlSHRINK (ctxt);
1981
1982 static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
1983     xmlParserInputShrink(ctxt->input);
1984     if ((*ctxt->input->cur == 0) &&
1985         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
1986             xmlPopInput(ctxt);
1987   }
1988
1989 #define GROW if ((ctxt->progressive == 0) &&                            \
1990                  (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
1991         xmlGROW (ctxt);
1992
1993 static void xmlGROW (xmlParserCtxtPtr ctxt) {
1994     xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
1995     if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
1996         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
1997             xmlPopInput(ctxt);
1998 }
1999
2000 #define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2001
2002 #define NEXT xmlNextChar(ctxt)
2003
2004 #define NEXT1 {                                                         \
2005         ctxt->input->col++;                                             \
2006         ctxt->input->cur++;                                             \
2007         ctxt->nbChars++;                                                \
2008         if (*ctxt->input->cur == 0)                                     \
2009             xmlParserInputGrow(ctxt->input, INPUT_CHUNK);               \
2010     }
2011
2012 #define NEXTL(l) do {                                                   \
2013     if (*(ctxt->input->cur) == '\n') {                                  \
2014         ctxt->input->line++; ctxt->input->col = 1;                      \
2015     } else ctxt->input->col++;                                          \
2016     ctxt->input->cur += l;                              \
2017     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
2018   } while (0)
2019
2020 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2021 #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2022
2023 #define COPY_BUF(l,b,i,v)                                               \
2024     if (l == 1) b[i++] = (xmlChar) v;                                   \
2025     else i += xmlCopyCharMultiByte(&b[i],v)
2026
2027 /**
2028  * xmlSkipBlankChars:
2029  * @ctxt:  the XML parser context
2030  *
2031  * skip all blanks character found at that point in the input streams.
2032  * It pops up finished entities in the process if allowable at that point.
2033  *
2034  * Returns the number of space chars skipped
2035  */
2036
2037 int
2038 xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2039     int res = 0;
2040
2041     /*
2042      * It's Okay to use CUR/NEXT here since all the blanks are on
2043      * the ASCII range.
2044      */
2045     if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
2046         const xmlChar *cur;
2047         /*
2048          * if we are in the document content, go really fast
2049          */
2050         cur = ctxt->input->cur;
2051         while (IS_BLANK_CH(*cur)) {
2052             if (*cur == '\n') {
2053                 ctxt->input->line++; ctxt->input->col = 1;
2054             }
2055             cur++;
2056             res++;
2057             if (*cur == 0) {
2058                 ctxt->input->cur = cur;
2059                 xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2060                 cur = ctxt->input->cur;
2061             }
2062         }
2063         ctxt->input->cur = cur;
2064     } else {
2065         int cur;
2066         do {
2067             cur = CUR;
2068             while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
2069                 NEXT;
2070                 cur = CUR;
2071                 res++;
2072             }
2073             while ((cur == 0) && (ctxt->inputNr > 1) &&
2074                    (ctxt->instate != XML_PARSER_COMMENT)) {
2075                 xmlPopInput(ctxt);
2076                 cur = CUR;
2077             }
2078             /*
2079              * Need to handle support of entities branching here
2080              */
2081             if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
2082         } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
2083     }
2084     return(res);
2085 }
2086
2087 /************************************************************************
2088  *                                                                      *
2089  *              Commodity functions to handle entities                  *
2090  *                                                                      *
2091  ************************************************************************/
2092
2093 /**
2094  * xmlPopInput:
2095  * @ctxt:  an XML parser context
2096  *
2097  * xmlPopInput: the current input pointed by ctxt->input came to an end
2098  *          pop it and return the next char.
2099  *
2100  * Returns the current xmlChar in the parser context
2101  */
2102 xmlChar
2103 xmlPopInput(xmlParserCtxtPtr ctxt) {
2104     if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2105     if (xmlParserDebugEntities)
2106         xmlGenericError(xmlGenericErrorContext,
2107                 "Popping input %d\n", ctxt->inputNr);
2108     xmlFreeInputStream(inputPop(ctxt));
2109     if ((*ctxt->input->cur == 0) &&
2110         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2111             return(xmlPopInput(ctxt));
2112     return(CUR);
2113 }
2114
2115 /**
2116  * xmlPushInput:
2117  * @ctxt:  an XML parser context
2118  * @input:  an XML parser input fragment (entity, XML fragment ...).
2119  *
2120  * xmlPushInput: switch to a new input stream which is stacked on top
2121  *               of the previous one(s).
2122  * Returns -1 in case of error or the index in the input stack
2123  */
2124 int
2125 xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2126     int ret;
2127     if (input == NULL) return(-1);
2128
2129     if (xmlParserDebugEntities) {
2130         if ((ctxt->input != NULL) && (ctxt->input->filename))
2131             xmlGenericError(xmlGenericErrorContext,
2132                     "%s(%d): ", ctxt->input->filename,
2133                     ctxt->input->line);
2134         xmlGenericError(xmlGenericErrorContext,
2135                 "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2136     }
2137     ret = inputPush(ctxt, input);
2138     GROW;
2139     return(ret);
2140 }
2141
2142 /**
2143  * xmlParseCharRef:
2144  * @ctxt:  an XML parser context
2145  *
2146  * parse Reference declarations
2147  *
2148  * [66] CharRef ::= '&#' [0-9]+ ';' |
2149  *                  '&#x' [0-9a-fA-F]+ ';'
2150  *
2151  * [ WFC: Legal Character ]
2152  * Characters referred to using character references must match the
2153  * production for Char. 
2154  *
2155  * Returns the value parsed (as an int), 0 in case of error
2156  */
2157 int
2158 xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2159     unsigned int val = 0;
2160     int count = 0;
2161     unsigned int outofrange = 0;
2162
2163     /*
2164      * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2165      */
2166     if ((RAW == '&') && (NXT(1) == '#') &&
2167         (NXT(2) == 'x')) {
2168         SKIP(3);
2169         GROW;
2170         while (RAW != ';') { /* loop blocked by count */
2171             if (count++ > 20) {
2172                 count = 0;
2173                 GROW;
2174             }
2175             if ((RAW >= '0') && (RAW <= '9')) 
2176                 val = val * 16 + (CUR - '0');
2177             else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2178                 val = val * 16 + (CUR - 'a') + 10;
2179             else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2180                 val = val * 16 + (CUR - 'A') + 10;
2181             else {
2182                 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2183                 val = 0;
2184                 break;
2185             }
2186             if (val > 0x10FFFF)
2187                 outofrange = val;
2188
2189             NEXT;
2190             count++;
2191         }
2192         if (RAW == ';') {
2193             /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2194             ctxt->input->col++;
2195             ctxt->nbChars ++;
2196             ctxt->input->cur++;
2197         }
2198     } else if  ((RAW == '&') && (NXT(1) == '#')) {
2199         SKIP(2);
2200         GROW;
2201         while (RAW != ';') { /* loop blocked by count */
2202             if (count++ > 20) {
2203                 count = 0;
2204                 GROW;
2205             }
2206             if ((RAW >= '0') && (RAW <= '9')) 
2207                 val = val * 10 + (CUR - '0');
2208             else {
2209                 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2210                 val = 0;
2211                 break;
2212             }
2213             if (val > 0x10FFFF)
2214                 outofrange = val;
2215
2216             NEXT;
2217             count++;
2218         }
2219         if (RAW == ';') {
2220             /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2221             ctxt->input->col++;
2222             ctxt->nbChars ++;
2223             ctxt->input->cur++;
2224         }
2225     } else {
2226         xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2227     }
2228
2229     /*
2230      * [ WFC: Legal Character ]
2231      * Characters referred to using character references must match the
2232      * production for Char. 
2233      */
2234     if ((IS_CHAR(val) && (outofrange == 0))) {
2235         return(val);
2236     } else {
2237         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2238                           "xmlParseCharRef: invalid xmlChar value %d\n",
2239                           val);
2240     }
2241     return(0);
2242 }
2243
2244 /**
2245  * xmlParseStringCharRef:
2246  * @ctxt:  an XML parser context
2247  * @str:  a pointer to an index in the string
2248  *
2249  * parse Reference declarations, variant parsing from a string rather
2250  * than an an input flow.
2251  *
2252  * [66] CharRef ::= '&#' [0-9]+ ';' |
2253  *                  '&#x' [0-9a-fA-F]+ ';'
2254  *
2255  * [ WFC: Legal Character ]
2256  * Characters referred to using character references must match the
2257  * production for Char. 
2258  *
2259  * Returns the value parsed (as an int), 0 in case of error, str will be
2260  *         updated to the current value of the index
2261  */
2262 static int
2263 xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2264     const xmlChar *ptr;
2265     xmlChar cur;
2266     unsigned int val = 0;
2267     unsigned int outofrange = 0;
2268
2269     if ((str == NULL) || (*str == NULL)) return(0);
2270     ptr = *str;
2271     cur = *ptr;
2272     if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2273         ptr += 3;
2274         cur = *ptr;
2275         while (cur != ';') { /* Non input consuming loop */
2276             if ((cur >= '0') && (cur <= '9')) 
2277                 val = val * 16 + (cur - '0');
2278             else if ((cur >= 'a') && (cur <= 'f'))
2279                 val = val * 16 + (cur - 'a') + 10;
2280             else if ((cur >= 'A') && (cur <= 'F'))
2281                 val = val * 16 + (cur - 'A') + 10;
2282             else {
2283                 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2284                 val = 0;
2285                 break;
2286             }
2287             if (val > 0x10FFFF)
2288                 outofrange = val;
2289
2290             ptr++;
2291             cur = *ptr;
2292         }
2293         if (cur == ';')
2294             ptr++;
2295     } else if  ((cur == '&') && (ptr[1] == '#')){
2296         ptr += 2;
2297         cur = *ptr;
2298         while (cur != ';') { /* Non input consuming loops */
2299             if ((cur >= '0') && (cur <= '9')) 
2300                 val = val * 10 + (cur - '0');
2301             else {
2302                 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2303                 val = 0;
2304                 break;
2305             }
2306             if (val > 0x10FFFF)
2307                 outofrange = val;
2308
2309             ptr++;
2310             cur = *ptr;
2311         }
2312         if (cur == ';')
2313             ptr++;
2314     } else {
2315         xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2316         return(0);
2317     }
2318     *str = ptr;
2319
2320     /*
2321      * [ WFC: Legal Character ]
2322      * Characters referred to using character references must match the
2323      * production for Char. 
2324      */
2325     if ((IS_CHAR(val) && (outofrange == 0))) {
2326         return(val);
2327     } else {
2328         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2329                           "xmlParseStringCharRef: invalid xmlChar value %d\n",
2330                           val);
2331     }
2332     return(0);
2333 }
2334
2335 /**
2336  * xmlNewBlanksWrapperInputStream:
2337  * @ctxt:  an XML parser context
2338  * @entity:  an Entity pointer
2339  *
2340  * Create a new input stream for wrapping
2341  * blanks around a PEReference
2342  *
2343  * Returns the new input stream or NULL
2344  */
2345  
2346 static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
2347  
2348 static xmlParserInputPtr
2349 xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
2350     xmlParserInputPtr input;
2351     xmlChar *buffer;
2352     size_t length;
2353     if (entity == NULL) {
2354         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2355                     "xmlNewBlanksWrapperInputStream entity\n");
2356         return(NULL);
2357     }
2358     if (xmlParserDebugEntities)
2359         xmlGenericError(xmlGenericErrorContext,
2360                 "new blanks wrapper for entity: %s\n", entity->name);
2361     input = xmlNewInputStream(ctxt);
2362     if (input == NULL) {
2363         return(NULL);
2364     }
2365     length = xmlStrlen(entity->name) + 5;
2366     buffer = xmlMallocAtomic(length);
2367     if (buffer == NULL) {
2368         xmlErrMemory(ctxt, NULL);
2369         xmlFree(input);
2370         return(NULL);
2371     }
2372     buffer [0] = ' ';
2373     buffer [1] = '%';
2374     buffer [length-3] = ';';
2375     buffer [length-2] = ' ';
2376     buffer [length-1] = 0;
2377     memcpy(buffer + 2, entity->name, length - 5);
2378     input->free = deallocblankswrapper;
2379     input->base = buffer;
2380     input->cur = buffer;
2381     input->length = length;
2382     input->end = &buffer[length];
2383     return(input);
2384 }
2385
2386 /**
2387  * xmlParserHandlePEReference:
2388  * @ctxt:  the parser context
2389  * 
2390  * [69] PEReference ::= '%' Name ';'
2391  *
2392  * [ WFC: No Recursion ]
2393  * A parsed entity must not contain a recursive
2394  * reference to itself, either directly or indirectly. 
2395  *
2396  * [ WFC: Entity Declared ]
2397  * In a document without any DTD, a document with only an internal DTD
2398  * subset which contains no parameter entity references, or a document
2399  * with "standalone='yes'", ...  ... The declaration of a parameter
2400  * entity must precede any reference to it...
2401  *
2402  * [ VC: Entity Declared ]
2403  * In a document with an external subset or external parameter entities
2404  * with "standalone='no'", ...  ... The declaration of a parameter entity
2405  * must precede any reference to it...
2406  *
2407  * [ WFC: In DTD ]
2408  * Parameter-entity references may only appear in the DTD.
2409  * NOTE: misleading but this is handled.
2410  *
2411  * A PEReference may have been detected in the current input stream
2412  * the handling is done accordingly to 
2413  *      http://www.w3.org/TR/REC-xml#entproc
2414  * i.e. 
2415  *   - Included in literal in entity values
2416  *   - Included as Parameter Entity reference within DTDs
2417  */
2418 void
2419 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2420     const xmlChar *name;
2421     xmlEntityPtr entity = NULL;
2422     xmlParserInputPtr input;
2423
2424     if (RAW != '%') return;
2425     switch(ctxt->instate) {
2426         case XML_PARSER_CDATA_SECTION:
2427             return;
2428         case XML_PARSER_COMMENT:
2429             return;
2430         case XML_PARSER_START_TAG:
2431             return;
2432         case XML_PARSER_END_TAG:
2433             return;
2434         case XML_PARSER_EOF:
2435             xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2436             return;
2437         case XML_PARSER_PROLOG:
2438         case XML_PARSER_START:
2439         case XML_PARSER_MISC:
2440             xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2441             return;
2442         case XML_PARSER_ENTITY_DECL:
2443         case XML_PARSER_CONTENT:
2444         case XML_PARSER_ATTRIBUTE_VALUE:
2445         case XML_PARSER_PI:
2446         case XML_PARSER_SYSTEM_LITERAL:
2447         case XML_PARSER_PUBLIC_LITERAL:
2448             /* we just ignore it there */
2449             return;
2450         case XML_PARSER_EPILOG:
2451             xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2452             return;
2453         case XML_PARSER_ENTITY_VALUE:
2454             /*
2455              * NOTE: in the case of entity values, we don't do the
2456              *       substitution here since we need the literal
2457              *       entity value to be able to save the internal
2458              *       subset of the document.
2459              *       This will be handled by xmlStringDecodeEntities
2460              */
2461             return;
2462         case XML_PARSER_DTD:
2463             /*
2464              * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2465              * In the internal DTD subset, parameter-entity references
2466              * can occur only where markup declarations can occur, not
2467              * within markup declarations.
2468              * In that case this is handled in xmlParseMarkupDecl
2469              */
2470             if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2471                 return;
2472             if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2473                 return;
2474             break;
2475         case XML_PARSER_IGNORE:
2476             return;
2477     }
2478
2479     NEXT;
2480     name = xmlParseName(ctxt);
2481     if (xmlParserDebugEntities)
2482         xmlGenericError(xmlGenericErrorContext,
2483                 "PEReference: %s\n", name);
2484     if (name == NULL) {
2485         xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
2486     } else {
2487         if (RAW == ';') {
2488             NEXT;
2489             if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
2490                 entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
2491             if (entity == NULL) {
2492                 
2493                 /*
2494                  * [ WFC: Entity Declared ]
2495                  * In a document without any DTD, a document with only an
2496                  * internal DTD subset which contains no parameter entity
2497                  * references, or a document with "standalone='yes'", ...
2498                  * ... The declaration of a parameter entity must precede
2499                  * any reference to it...
2500                  */
2501                 if ((ctxt->standalone == 1) ||
2502                     ((ctxt->hasExternalSubset == 0) &&
2503                      (ctxt->hasPErefs == 0))) {
2504                     xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
2505                          "PEReference: %%%s; not found\n", name);
2506                 } else {
2507                     /*
2508                      * [ VC: Entity Declared ]
2509                      * In a document with an external subset or external
2510                      * parameter entities with "standalone='no'", ...
2511                      * ... The declaration of a parameter entity must precede
2512                      * any reference to it...
2513                      */
2514                     if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
2515                         xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
2516                                          "PEReference: %%%s; not found\n",
2517                                          name, NULL);
2518                     } else 
2519                         xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
2520                                       "PEReference: %%%s; not found\n",
2521                                       name, NULL);
2522                     ctxt->valid = 0;
2523                 }
2524             } else if (ctxt->input->free != deallocblankswrapper) {
2525                     input = xmlNewBlanksWrapperInputStream(ctxt, entity);
2526                     if (xmlPushInput(ctxt, input) < 0)
2527                         return;
2528             } else {
2529                 if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
2530                     (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
2531                     xmlChar start[4];
2532                     xmlCharEncoding enc;
2533
2534                     /*
2535                      * handle the extra spaces added before and after
2536                      * c.f. http://www.w3.org/TR/REC-xml#as-PE
2537                      * this is done independently.
2538                      */
2539                     input = xmlNewEntityInputStream(ctxt, entity);
2540                     if (xmlPushInput(ctxt, input) < 0)
2541                         return;
2542
2543                     /* 
2544                      * Get the 4 first bytes and decode the charset
2545                      * if enc != XML_CHAR_ENCODING_NONE
2546                      * plug some encoding conversion routines.
2547                      * Note that, since we may have some non-UTF8
2548                      * encoding (like UTF16, bug 135229), the 'length'
2549                      * is not known, but we can calculate based upon
2550                      * the amount of data in the buffer.
2551                      */
2552                     GROW
2553                     if ((ctxt->input->end - ctxt->input->cur)>=4) {
2554                         start[0] = RAW;
2555                         start[1] = NXT(1);
2556                         start[2] = NXT(2);
2557                         start[3] = NXT(3);
2558                         enc = xmlDetectCharEncoding(start, 4);
2559                         if (enc != XML_CHAR_ENCODING_NONE) {
2560                             xmlSwitchEncoding(ctxt, enc);
2561                         }
2562                     }
2563
2564                     if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2565                         (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
2566                         (IS_BLANK_CH(NXT(5)))) {
2567                         xmlParseTextDecl(ctxt);
2568                     }
2569                 } else {
2570                     xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
2571                              "PEReference: %s is not a parameter entity\n",
2572                                       name);
2573                 }
2574             }
2575         } else {
2576             xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
2577         }
2578     }
2579 }
2580
2581 /*
2582  * Macro used to grow the current buffer.
2583  */
2584 #define growBuffer(buffer, n) {                                         \
2585     xmlChar *tmp;                                                       \
2586     buffer##_size *= 2;                                                 \
2587     buffer##_size += n;                                                 \
2588     tmp = (xmlChar *)                                                   \
2589                 xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
2590     if (tmp == NULL) goto mem_error;                                    \
2591     buffer = tmp;                                                       \
2592 }
2593
2594 /**
2595  * xmlStringLenDecodeEntities:
2596  * @ctxt:  the parser context
2597  * @str:  the input string
2598  * @len: the string length
2599  * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2600  * @end:  an end marker xmlChar, 0 if none
2601  * @end2:  an end marker xmlChar, 0 if none
2602  * @end3:  an end marker xmlChar, 0 if none
2603  * 
2604  * Takes a entity string content and process to do the adequate substitutions.
2605  *
2606  * [67] Reference ::= EntityRef | CharRef
2607  *
2608  * [69] PEReference ::= '%' Name ';'
2609  *
2610  * Returns A newly allocated string with the substitution done. The caller
2611  *      must deallocate it !
2612  */
2613 xmlChar *
2614 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2615                       int what, xmlChar end, xmlChar  end2, xmlChar end3) {
2616     xmlChar *buffer = NULL;
2617     int buffer_size = 0;
2618
2619     xmlChar *current = NULL;
2620     xmlChar *rep = NULL;
2621     const xmlChar *last;
2622     xmlEntityPtr ent;
2623     int c,l;
2624     int nbchars = 0;
2625
2626     if ((ctxt == NULL) || (str == NULL) || (len < 0))
2627         return(NULL);
2628     last = str + len;
2629
2630     if (((ctxt->depth > 40) &&
2631          ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2632         (ctxt->depth > 1024)) {
2633         xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2634         return(NULL);
2635     }
2636
2637     /*
2638      * allocate a translation buffer.
2639      */
2640     buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2641     buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
2642     if (buffer == NULL) goto mem_error;
2643
2644     /*
2645      * OK loop until we reach one of the ending char or a size limit.
2646      * we are operating on already parsed values.
2647      */
2648     if (str < last)
2649         c = CUR_SCHAR(str, l);
2650     else
2651         c = 0;
2652     while ((c != 0) && (c != end) && /* non input consuming loop */
2653            (c != end2) && (c != end3)) {
2654
2655         if (c == 0) break;
2656         if ((c == '&') && (str[1] == '#')) {
2657             int val = xmlParseStringCharRef(ctxt, &str);
2658             if (val != 0) {
2659                 COPY_BUF(0,buffer,nbchars,val);
2660             }
2661             if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
2662                 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2663             }
2664         } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2665             if (xmlParserDebugEntities)
2666                 xmlGenericError(xmlGenericErrorContext,
2667                         "String decoding Entity Reference: %.30s\n",
2668                         str);
2669             ent = xmlParseStringEntityRef(ctxt, &str);
2670             if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
2671                 (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
2672                 goto int_error;
2673             if (ent != NULL)
2674                 ctxt->nbentities += ent->checked;
2675             if ((ent != NULL) &&
2676                 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2677                 if (ent->content != NULL) {
2678                     COPY_BUF(0,buffer,nbchars,ent->content[0]);
2679                     if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
2680                         growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2681                     }
2682                 } else {
2683                     xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2684                             "predefined entity has no content\n");
2685                 }
2686             } else if ((ent != NULL) && (ent->content != NULL)) {
2687                 ctxt->depth++;
2688                 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2689                                               0, 0, 0);
2690                 ctxt->depth--;
2691
2692                 if (rep != NULL) {
2693                     current = rep;
2694                     while (*current != 0) { /* non input consuming loop */
2695                         buffer[nbchars++] = *current++;
2696                         if (nbchars >
2697                             buffer_size - XML_PARSER_BUFFER_SIZE) {
2698                             if (xmlParserEntityCheck(ctxt, nbchars, ent))
2699                                 goto int_error;
2700                             growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2701                         }
2702                     }
2703                     xmlFree(rep);
2704                     rep = NULL;
2705                 }
2706             } else if (ent != NULL) {
2707                 int i = xmlStrlen(ent->name);
2708                 const xmlChar *cur = ent->name;
2709
2710                 buffer[nbchars++] = '&';
2711                 if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
2712                     growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2713                 }
2714                 for (;i > 0;i--)
2715                     buffer[nbchars++] = *cur++;
2716                 buffer[nbchars++] = ';';
2717             }
2718         } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2719             if (xmlParserDebugEntities)
2720                 xmlGenericError(xmlGenericErrorContext,
2721                         "String decoding PE Reference: %.30s\n", str);
2722             ent = xmlParseStringPEReference(ctxt, &str);
2723             if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
2724                 goto int_error;
2725             if (ent != NULL)
2726                 ctxt->nbentities += ent->checked;
2727             if (ent != NULL) {
2728                 if (ent->content == NULL) {
2729                     xmlLoadEntityContent(ctxt, ent);
2730                 }
2731                 ctxt->depth++;
2732                 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2733                                               0, 0, 0);
2734                 ctxt->depth--;
2735                 if (rep != NULL) {
2736                     current = rep;
2737                     while (*current != 0) { /* non input consuming loop */
2738                         buffer[nbchars++] = *current++;
2739                         if (nbchars >
2740                             buffer_size - XML_PARSER_BUFFER_SIZE) {
2741                             if (xmlParserEntityCheck(ctxt, nbchars, ent))
2742                                 goto int_error;
2743                             growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2744                         }
2745                     }
2746                     xmlFree(rep);
2747                     rep = NULL;
2748                 }
2749             }
2750         } else {
2751             COPY_BUF(l,buffer,nbchars,c);
2752             str += l;
2753             if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
2754               growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2755             }
2756         }
2757         if (str < last)
2758             c = CUR_SCHAR(str, l);
2759         else
2760             c = 0;
2761     }
2762     buffer[nbchars] = 0;
2763     return(buffer);
2764
2765 mem_error:
2766     xmlErrMemory(ctxt, NULL);
2767 int_error:
2768     if (rep != NULL)
2769         xmlFree(rep);
2770     if (buffer != NULL)
2771         xmlFree(buffer);
2772     return(NULL);
2773 }
2774
2775 /**
2776  * xmlStringDecodeEntities:
2777  * @ctxt:  the parser context
2778  * @str:  the input string
2779  * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2780  * @end:  an end marker xmlChar, 0 if none
2781  * @end2:  an end marker xmlChar, 0 if none
2782  * @end3:  an end marker xmlChar, 0 if none
2783  * 
2784  * Takes a entity string content and process to do the adequate substitutions.
2785  *
2786  * [67] Reference ::= EntityRef | CharRef
2787  *
2788  * [69] PEReference ::= '%' Name ';'
2789  *
2790  * Returns A newly allocated string with the substitution done. The caller
2791  *      must deallocate it !
2792  */
2793 xmlChar *
2794 xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2795                         xmlChar end, xmlChar  end2, xmlChar end3) {
2796     if ((ctxt == NULL) || (str == NULL)) return(NULL);
2797     return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2798            end, end2, end3));
2799 }
2800
2801 /************************************************************************
2802  *                                                                      *
2803  *              Commodity functions, cleanup needed ?                   *
2804  *                                                                      *
2805  ************************************************************************/
2806
2807 /**
2808  * areBlanks:
2809  * @ctxt:  an XML parser context
2810  * @str:  a xmlChar *
2811  * @len:  the size of @str
2812  * @blank_chars: we know the chars are blanks
2813  *
2814  * Is this a sequence of blank chars that one can ignore ?
2815  *
2816  * Returns 1 if ignorable 0 otherwise.
2817  */
2818
2819 static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2820                      int blank_chars) {
2821     int i, ret;
2822     xmlNodePtr lastChild;
2823
2824     /*
2825      * Don't spend time trying to differentiate them, the same callback is
2826      * used !
2827      */
2828     if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2829         return(0);
2830
2831     /*
2832      * Check for xml:space value.
2833      */
2834     if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2835         (*(ctxt->space) == -2))
2836         return(0);
2837
2838     /*
2839      * Check that the string is made of blanks
2840      */
2841     if (blank_chars == 0) {
2842         for (i = 0;i < len;i++)
2843             if (!(IS_BLANK_CH(str[i]))) return(0);
2844     }
2845
2846     /*
2847      * Look if the element is mixed content in the DTD if available
2848      */
2849     if (ctxt->node == NULL) return(0);
2850     if (ctxt->myDoc != NULL) {
2851         ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2852         if (ret == 0) return(1);
2853         if (ret == 1) return(0);
2854     }
2855
2856     /*
2857      * Otherwise, heuristic :-\
2858      */
2859     if ((RAW != '<') && (RAW != 0xD)) return(0);
2860     if ((ctxt->node->children == NULL) &&
2861         (RAW == '<') && (NXT(1) == '/')) return(0);
2862
2863     lastChild = xmlGetLastChild(ctxt->node);
2864     if (lastChild == NULL) {
2865         if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2866             (ctxt->node->content != NULL)) return(0);
2867     } else if (xmlNodeIsText(lastChild))
2868         return(0);
2869     else if ((ctxt->node->children != NULL) &&
2870              (xmlNodeIsText(ctxt->node->children)))
2871         return(0);
2872     return(1);
2873 }
2874
2875 /************************************************************************
2876  *                                                                      *
2877  *              Extra stuff for namespace support                       *
2878  *      Relates to http://www.w3.org/TR/WD-xml-names                    *
2879  *                                                                      *
2880  ************************************************************************/
2881
2882 /**
2883  * xmlSplitQName:
2884  * @ctxt:  an XML parser context
2885  * @name:  an XML parser context
2886  * @prefix:  a xmlChar **
2887  *
2888  * parse an UTF8 encoded XML qualified name string
2889  *
2890  * [NS 5] QName ::= (Prefix ':')? LocalPart
2891  *
2892  * [NS 6] Prefix ::= NCName
2893  *
2894  * [NS 7] LocalPart ::= NCName
2895  *
2896  * Returns the local part, and prefix is updated
2897  *   to get the Prefix if any.
2898  */
2899
2900 xmlChar *
2901 xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2902     xmlChar buf[XML_MAX_NAMELEN + 5];
2903     xmlChar *buffer = NULL;
2904     int len = 0;
2905     int max = XML_MAX_NAMELEN;
2906     xmlChar *ret = NULL;
2907     const xmlChar *cur = name;
2908     int c;
2909
2910     if (prefix == NULL) return(NULL);
2911     *prefix = NULL;
2912
2913     if (cur == NULL) return(NULL);
2914
2915 #ifndef XML_XML_NAMESPACE
2916     /* xml: prefix is not really a namespace */
2917     if ((cur[0] == 'x') && (cur[1] == 'm') &&
2918         (cur[2] == 'l') && (cur[3] == ':'))
2919         return(xmlStrdup(name));
2920 #endif
2921
2922     /* nasty but well=formed */
2923     if (cur[0] == ':')
2924         return(xmlStrdup(name));
2925
2926     c = *cur++;
2927     while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2928         buf[len++] = c;
2929         c = *cur++;
2930     }
2931     if (len >= max) {
2932         /*
2933          * Okay someone managed to make a huge name, so he's ready to pay
2934          * for the processing speed.
2935          */
2936         max = len * 2;
2937
2938         buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2939         if (buffer == NULL) {
2940             xmlErrMemory(ctxt, NULL);
2941             return(NULL);
2942         }
2943         memcpy(buffer, buf, len);
2944         while ((c != 0) && (c != ':')) { /* tested bigname.xml */
2945             if (len + 10 > max) {
2946                 xmlChar *tmp;
2947
2948                 max *= 2;
2949                 tmp = (xmlChar *) xmlRealloc(buffer,
2950                                                 max * sizeof(xmlChar));
2951                 if (tmp == NULL) {
2952                     xmlFree(buffer);
2953                     xmlErrMemory(ctxt, NULL);
2954                     return(NULL);
2955                 }
2956                 buffer = tmp;
2957             }
2958             buffer[len++] = c;
2959             c = *cur++;
2960         }
2961         buffer[len] = 0;
2962     }
2963
2964     if ((c == ':') && (*cur == 0)) {
2965         if (buffer != NULL)
2966             xmlFree(buffer);
2967         *prefix = NULL;
2968         return(xmlStrdup(name));
2969     }
2970
2971     if (buffer == NULL)
2972         ret = xmlStrndup(buf, len);
2973     else {
2974         ret = buffer;
2975         buffer = NULL;
2976         max = XML_MAX_NAMELEN;
2977     }
2978
2979
2980     if (c == ':') {
2981         c = *cur;
2982         *prefix = ret;
2983         if (c == 0) {
2984             return(xmlStrndup(BAD_CAST "", 0));
2985         }
2986         len = 0;
2987
2988         /*
2989          * Check that the first character is proper to start
2990          * a new name
2991          */
2992         if (!(((c >= 0x61) && (c <= 0x7A)) ||
2993               ((c >= 0x41) && (c <= 0x5A)) ||
2994               (c == '_') || (c == ':'))) {
2995             int l;
2996             int first = CUR_SCHAR(cur, l);
2997
2998             if (!IS_LETTER(first) && (first != '_')) {
2999                 xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3000                             "Name %s is not XML Namespace compliant\n",
3001                                   name);
3002             }
3003         }
3004         cur++;
3005
3006         while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3007             buf[len++] = c;
3008             c = *cur++;
3009         }
3010         if (len >= max) {
3011             /*
3012              * Okay someone managed to make a huge name, so he's ready to pay
3013              * for the processing speed.
3014              */
3015             max = len * 2;
3016
3017             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3018             if (buffer == NULL) {
3019                 xmlErrMemory(ctxt, NULL);
3020                 return(NULL);
3021             }
3022             memcpy(buffer, buf, len);
3023             while (c != 0) { /* tested bigname2.xml */
3024                 if (len + 10 > max) {
3025                     xmlChar *tmp;
3026
3027                     max *= 2;
3028                     tmp = (xmlChar *) xmlRealloc(buffer,
3029                                                     max * sizeof(xmlChar));
3030                     if (tmp == NULL) {
3031                         xmlErrMemory(ctxt, NULL);
3032                         xmlFree(buffer);
3033                         return(NULL);
3034                     }
3035                     buffer = tmp;
3036                 }
3037                 buffer[len++] = c;
3038                 c = *cur++;
3039             }
3040             buffer[len] = 0;
3041         }
3042
3043         if (buffer == NULL)
3044             ret = xmlStrndup(buf, len);
3045         else {
3046             ret = buffer;
3047         }
3048     }
3049
3050     return(ret);
3051 }
3052
3053 /************************************************************************
3054  *                                                                      *
3055  *                      The parser itself                               *
3056  *      Relates to http://www.w3.org/TR/REC-xml                         *
3057  *                                                                      *
3058  ************************************************************************/
3059
3060 /************************************************************************
3061  *                                                                      *
3062  *      Routines to parse Name, NCName and NmToken                      *
3063  *                                                                      *
3064  ************************************************************************/
3065 #ifdef DEBUG
3066 static unsigned long nbParseName = 0;
3067 static unsigned long nbParseNmToken = 0;
3068 static unsigned long nbParseNCName = 0;
3069 static unsigned long nbParseNCNameComplex = 0;
3070 static unsigned long nbParseNameComplex = 0;
3071 static unsigned long nbParseStringName = 0;
3072 #endif
3073
3074 /*
3075  * The two following functions are related to the change of accepted
3076  * characters for Name and NmToken in the Revision 5 of XML-1.0
3077  * They correspond to the modified production [4] and the new production [4a]
3078  * changes in that revision. Also note that the macros used for the
3079  * productions Letter, Digit, CombiningChar and Extender are not needed
3080  * anymore.
3081  * We still keep compatibility to pre-revision5 parsing semantic if the
3082  * new XML_PARSE_OLD10 option is given to the parser.
3083  */
3084 static int
3085 xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3086     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3087         /*
3088          * Use the new checks of production [4] [4a] amd [5] of the
3089          * Update 5 of XML-1.0
3090          */
3091         if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3092             (((c >= 'a') && (c <= 'z')) ||
3093              ((c >= 'A') && (c <= 'Z')) ||
3094              (c == '_') || (c == ':') ||
3095              ((c >= 0xC0) && (c <= 0xD6)) ||
3096              ((c >= 0xD8) && (c <= 0xF6)) ||
3097              ((c >= 0xF8) && (c <= 0x2FF)) ||
3098              ((c >= 0x370) && (c <= 0x37D)) ||
3099              ((c >= 0x37F) && (c <= 0x1FFF)) ||
3100              ((c >= 0x200C) && (c <= 0x200D)) ||
3101              ((c >= 0x2070) && (c <= 0x218F)) ||
3102              ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3103              ((c >= 0x3001) && (c <= 0xD7FF)) ||
3104              ((c >= 0xF900) && (c <= 0xFDCF)) ||
3105              ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3106              ((c >= 0x10000) && (c <= 0xEFFFF))))
3107             return(1);
3108     } else {
3109         if (IS_LETTER(c) || (c == '_') || (c == ':'))
3110             return(1);
3111     }
3112     return(0);
3113 }
3114
3115 static int
3116 xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3117     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3118         /*
3119          * Use the new checks of production [4] [4a] amd [5] of the
3120          * Update 5 of XML-1.0
3121          */
3122         if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3123             (((c >= 'a') && (c <= 'z')) ||
3124              ((c >= 'A') && (c <= 'Z')) ||
3125              ((c >= '0') && (c <= '9')) || /* !start */
3126              (c == '_') || (c == ':') ||
3127              (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3128              ((c >= 0xC0) && (c <= 0xD6)) ||
3129              ((c >= 0xD8) && (c <= 0xF6)) ||
3130              ((c >= 0xF8) && (c <= 0x2FF)) ||
3131              ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3132              ((c >= 0x370) && (c <= 0x37D)) ||
3133              ((c >= 0x37F) && (c <= 0x1FFF)) ||
3134              ((c >= 0x200C) && (c <= 0x200D)) ||
3135              ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3136              ((c >= 0x2070) && (c <= 0x218F)) ||
3137              ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3138              ((c >= 0x3001) && (c <= 0xD7FF)) ||
3139              ((c >= 0xF900) && (c <= 0xFDCF)) ||
3140              ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3141              ((c >= 0x10000) && (c <= 0xEFFFF))))
3142              return(1);
3143     } else {
3144         if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3145             (c == '.') || (c == '-') ||
3146             (c == '_') || (c == ':') || 
3147             (IS_COMBINING(c)) ||
3148             (IS_EXTENDER(c)))
3149             return(1);
3150     }
3151     return(0);
3152 }
3153
3154 static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3155                                           int *len, int *alloc, int normalize);
3156
3157 static const xmlChar *
3158 xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3159     int len = 0, l;
3160     int c;
3161     int count = 0;
3162
3163 #ifdef DEBUG
3164     nbParseNameComplex++;
3165 #endif
3166
3167     /*
3168      * Handler for more complex cases
3169      */
3170     GROW;
3171     c = CUR_CHAR(l);
3172     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3173         /*
3174          * Use the new checks of production [4] [4a] amd [5] of the
3175          * Update 5 of XML-1.0
3176          */
3177         if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3178             (!(((c >= 'a') && (c <= 'z')) ||
3179                ((c >= 'A') && (c <= 'Z')) ||
3180                (c == '_') || (c == ':') ||
3181                ((c >= 0xC0) && (c <= 0xD6)) ||
3182                ((c >= 0xD8) && (c <= 0xF6)) ||
3183                ((c >= 0xF8) && (c <= 0x2FF)) ||
3184                ((c >= 0x370) && (c <= 0x37D)) ||
3185                ((c >= 0x37F) && (c <= 0x1FFF)) ||
3186                ((c >= 0x200C) && (c <= 0x200D)) ||
3187                ((c >= 0x2070) && (c <= 0x218F)) ||
3188                ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3189                ((c >= 0x3001) && (c <= 0xD7FF)) ||
3190                ((c >= 0xF900) && (c <= 0xFDCF)) ||
3191                ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3192                ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3193             return(NULL);
3194         }
3195         len += l;
3196         NEXTL(l);
3197         c = CUR_CHAR(l);
3198         while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3199                (((c >= 'a') && (c <= 'z')) ||
3200                 ((c >= 'A') && (c <= 'Z')) ||
3201                 ((c >= '0') && (c <= '9')) || /* !start */
3202                 (c == '_') || (c == ':') ||
3203                 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3204                 ((c >= 0xC0) && (c <= 0xD6)) ||
3205                 ((c >= 0xD8) && (c <= 0xF6)) ||
3206                 ((c >= 0xF8) && (c <= 0x2FF)) ||
3207                 ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3208                 ((c >= 0x370) && (c <= 0x37D)) ||
3209                 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3210                 ((c >= 0x200C) && (c <= 0x200D)) ||
3211                 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3212                 ((c >= 0x2070) && (c <= 0x218F)) ||
3213                 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3214                 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3215                 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3216                 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3217                 ((c >= 0x10000) && (c <= 0xEFFFF))
3218                 )) {
3219             if (count++ > 100) {
3220                 count = 0;
3221                 GROW;
3222             }
3223             len += l;
3224             NEXTL(l);
3225             c = CUR_CHAR(l);
3226         }
3227     } else {
3228         if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3229             (!IS_LETTER(c) && (c != '_') &&
3230              (c != ':'))) {
3231             return(NULL);
3232         }
3233         len += l;
3234         NEXTL(l);
3235         c = CUR_CHAR(l);
3236
3237         while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3238                ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3239                 (c == '.') || (c == '-') ||
3240                 (c == '_') || (c == ':') || 
3241                 (IS_COMBINING(c)) ||
3242                 (IS_EXTENDER(c)))) {
3243             if (count++ > 100) {
3244                 count = 0;
3245                 GROW;
3246             }
3247             len += l;
3248             NEXTL(l);
3249             c = CUR_CHAR(l);
3250         }
3251     }
3252     if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3253         return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3254     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3255 }
3256
3257 /**
3258  * xmlParseName:
3259  * @ctxt:  an XML parser context
3260  *
3261  * parse an XML name.
3262  *
3263  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3264  *                  CombiningChar | Extender
3265  *
3266  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3267  *
3268  * [6] Names ::= Name (#x20 Name)*
3269  *
3270  * Returns the Name parsed or NULL
3271  */
3272
3273 const xmlChar *
3274 xmlParseName(xmlParserCtxtPtr ctxt) {
3275     const xmlChar *in;
3276     const xmlChar *ret;
3277     int count = 0;
3278
3279     GROW;
3280
3281 #ifdef DEBUG
3282     nbParseName++;
3283 #endif
3284
3285     /*
3286      * Accelerator for simple ASCII names
3287      */
3288     in = ctxt->input->cur;
3289     if (((*in >= 0x61) && (*in <= 0x7A)) ||
3290         ((*in >= 0x41) && (*in <= 0x5A)) ||
3291         (*in == '_') || (*in == ':')) {
3292         in++;
3293         while (((*in >= 0x61) && (*in <= 0x7A)) ||
3294                ((*in >= 0x41) && (*in <= 0x5A)) ||
3295                ((*in >= 0x30) && (*in <= 0x39)) ||
3296                (*in == '_') || (*in == '-') ||
3297                (*in == ':') || (*in == '.'))
3298             in++;
3299         if ((*in > 0) && (*in < 0x80)) {
3300             count = in - ctxt->input->cur;
3301             ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3302             ctxt->input->cur = in;
3303             ctxt->nbChars += count;
3304             ctxt->input->col += count;
3305             if (ret == NULL)
3306                 xmlErrMemory(ctxt, NULL);
3307             return(ret);
3308         }
3309     }
3310     /* accelerator for special cases */
3311     return(xmlParseNameComplex(ctxt));
3312 }
3313
3314 static const xmlChar *
3315 xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3316     int len = 0, l;
3317     int c;
3318     int count = 0;
3319
3320 #ifdef DEBUG
3321     nbParseNCNameComplex++;
3322 #endif
3323
3324     /*
3325      * Handler for more complex cases
3326      */
3327     GROW;
3328     c = CUR_CHAR(l);
3329     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3330         (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3331         return(NULL);
3332     }
3333
3334     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3335            (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3336         if (count++ > 100) {
3337             count = 0;
3338             GROW;
3339         }
3340         len += l;
3341         NEXTL(l);
3342         c = CUR_CHAR(l);
3343     }
3344     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3345 }
3346
3347 /**
3348  * xmlParseNCName:
3349  * @ctxt:  an XML parser context
3350  * @len:  lenght of the string parsed
3351  *
3352  * parse an XML name.
3353  *
3354  * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3355  *                      CombiningChar | Extender
3356  *
3357  * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3358  *
3359  * Returns the Name parsed or NULL
3360  */
3361
3362 static const xmlChar *
3363 xmlParseNCName(xmlParserCtxtPtr ctxt) {
3364     const xmlChar *in;
3365     const xmlChar *ret;
3366     int count = 0;
3367
3368 #ifdef DEBUG
3369     nbParseNCName++;
3370 #endif
3371
3372     /*
3373      * Accelerator for simple ASCII names
3374      */
3375     in = ctxt->input->cur;
3376     if (((*in >= 0x61) && (*in <= 0x7A)) ||
3377         ((*in >= 0x41) && (*in <= 0x5A)) ||
3378         (*in == '_')) {
3379         in++;
3380         while (((*in >= 0x61) && (*in <= 0x7A)) ||
3381                ((*in >= 0x41) && (*in <= 0x5A)) ||
3382                ((*in >= 0x30) && (*in <= 0x39)) ||
3383                (*in == '_') || (*in == '-') ||
3384                (*in == '.'))
3385             in++;
3386         if ((*in > 0) && (*in < 0x80)) {
3387             count = in - ctxt->input->cur;
3388             ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3389             ctxt->input->cur = in;
3390             ctxt->nbChars += count;
3391             ctxt->input->col += count;
3392             if (ret == NULL) {
3393                 xmlErrMemory(ctxt, NULL);
3394             }
3395             return(ret);
3396         }
3397     }
3398     return(xmlParseNCNameComplex(ctxt));
3399 }
3400
3401 /**
3402  * xmlParseNameAndCompare:
3403  * @ctxt:  an XML parser context
3404  *
3405  * parse an XML name and compares for match
3406  * (specialized for endtag parsing)
3407  *
3408  * Returns NULL for an illegal name, (xmlChar*) 1 for success
3409  * and the name for mismatch
3410  */
3411
3412 static const xmlChar *
3413 xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3414     register const xmlChar *cmp = other;
3415     register const xmlChar *in;
3416     const xmlChar *ret;
3417
3418     GROW;
3419
3420     in = ctxt->input->cur;
3421     while (*in != 0 && *in == *cmp) {
3422         ++in;
3423         ++cmp;
3424         ctxt->input->col++;
3425     }
3426     if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3427         /* success */
3428         ctxt->input->cur = in;
3429         return (const xmlChar*) 1;
3430     }
3431     /* failure (or end of input buffer), check with full function */
3432     ret = xmlParseName (ctxt);
3433     /* strings coming from the dictionnary direct compare possible */
3434     if (ret == other) {
3435         return (const xmlChar*) 1;
3436     }
3437     return ret;
3438 }
3439
3440 /**
3441  * xmlParseStringName:
3442  * @ctxt:  an XML parser context
3443  * @str:  a pointer to the string pointer (IN/OUT)
3444  *
3445  * parse an XML name.
3446  *
3447  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3448  *                  CombiningChar | Extender
3449  *
3450  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3451  *
3452  * [6] Names ::= Name (#x20 Name)*
3453  *
3454  * Returns the Name parsed or NULL. The @str pointer 
3455  * is updated to the current location in the string.
3456  */
3457
3458 static xmlChar *
3459 xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3460     xmlChar buf[XML_MAX_NAMELEN + 5];
3461     const xmlChar *cur = *str;
3462     int len = 0, l;
3463     int c;
3464
3465 #ifdef DEBUG
3466     nbParseStringName++;
3467 #endif
3468
3469     c = CUR_SCHAR(cur, l);
3470     if (!xmlIsNameStartChar(ctxt, c)) {
3471         return(NULL);
3472     }
3473
3474     COPY_BUF(l,buf,len,c);
3475     cur += l;
3476     c = CUR_SCHAR(cur, l);
3477     while (xmlIsNameChar(ctxt, c)) {
3478         COPY_BUF(l,buf,len,c);
3479         cur += l;
3480         c = CUR_SCHAR(cur, l);
3481         if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3482             /*
3483              * Okay someone managed to make a huge name, so he's ready to pay
3484              * for the processing speed.
3485              */
3486             xmlChar *buffer;
3487             int max = len * 2;
3488
3489             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3490             if (buffer == NULL) {
3491                 xmlErrMemory(ctxt, NULL);
3492                 return(NULL);
3493             }
3494             memcpy(buffer, buf, len);
3495             while (xmlIsNameChar(ctxt, c)) {
3496                 if (len + 10 > max) {
3497                     xmlChar *tmp;
3498                     max *= 2;
3499                     tmp = (xmlChar *) xmlRealloc(buffer,
3500                                                     max * sizeof(xmlChar));
3501                     if (tmp == NULL) {
3502                         xmlErrMemory(ctxt, NULL);
3503                         xmlFree(buffer);
3504                         return(NULL);
3505                     }
3506                     buffer = tmp;
3507                 }
3508                 COPY_BUF(l,buffer,len,c);
3509                 cur += l;
3510                 c = CUR_SCHAR(cur, l);
3511             }
3512             buffer[len] = 0;
3513             *str = cur;
3514             return(buffer);
3515         }
3516     }
3517     *str = cur;
3518     return(xmlStrndup(buf, len));
3519 }
3520
3521 /**
3522  * xmlParseNmtoken:
3523  * @ctxt:  an XML parser context
3524  *
3525  * parse an XML Nmtoken.
3526  *
3527  * [7] Nmtoken ::= (NameChar)+
3528  *
3529  * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3530  *
3531  * Returns the Nmtoken parsed or NULL
3532  */
3533
3534 xmlChar *
3535 xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3536     xmlChar buf[XML_MAX_NAMELEN + 5];
3537     int len = 0, l;
3538     int c;
3539     int count = 0;
3540
3541 #ifdef DEBUG
3542     nbParseNmToken++;
3543 #endif
3544
3545     GROW;
3546     c = CUR_CHAR(l);
3547
3548     while (xmlIsNameChar(ctxt, c)) {
3549         if (count++ > 100) {
3550             count = 0;
3551             GROW;
3552         }
3553         COPY_BUF(l,buf,len,c);
3554         NEXTL(l);
3555         c = CUR_CHAR(l);
3556         if (len >= XML_MAX_NAMELEN) {
3557             /*
3558              * Okay someone managed to make a huge token, so he's ready to pay
3559              * for the processing speed.
3560              */
3561             xmlChar *buffer;
3562             int max = len * 2;
3563
3564             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3565             if (buffer == NULL) {
3566                 xmlErrMemory(ctxt, NULL);
3567                 return(NULL);
3568             }
3569             memcpy(buffer, buf, len);
3570             while (xmlIsNameChar(ctxt, c)) {
3571                 if (count++ > 100) {
3572                     count = 0;
3573                     GROW;
3574                 }
3575                 if (len + 10 > max) {
3576                     xmlChar *tmp;
3577
3578                     max *= 2;
3579                     tmp = (xmlChar *) xmlRealloc(buffer,
3580                                                     max * sizeof(xmlChar));
3581                     if (tmp == NULL) {
3582                         xmlErrMemory(ctxt, NULL);
3583                         xmlFree(buffer);
3584                         return(NULL);
3585                     }
3586                     buffer = tmp;
3587                 }
3588                 COPY_BUF(l,buffer,len,c);
3589                 NEXTL(l);
3590                 c = CUR_CHAR(l);
3591             }
3592             buffer[len] = 0;
3593             return(buffer);
3594         }
3595     }
3596     if (len == 0)
3597         return(NULL);
3598     return(xmlStrndup(buf, len));
3599 }
3600
3601 /**
3602  * xmlParseEntityValue:
3603  * @ctxt:  an XML parser context
3604  * @orig:  if non-NULL store a copy of the original entity value
3605  *
3606  * parse a value for ENTITY declarations
3607  *
3608  * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3609  *                     "'" ([^%&'] | PEReference | Reference)* "'"
3610  *
3611  * Returns the EntityValue parsed with reference substituted or NULL
3612  */
3613
3614 xmlChar *
3615 xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3616     xmlChar *buf = NULL;
3617     int len = 0;
3618     int size = XML_PARSER_BUFFER_SIZE;
3619     int c, l;
3620     xmlChar stop;
3621     xmlChar *ret = NULL;
3622     const xmlChar *cur = NULL;
3623     xmlParserInputPtr input;
3624
3625     if (RAW == '"') stop = '"';
3626     else if (RAW == '\'') stop = '\'';
3627     else {
3628         xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3629         return(NULL);
3630     }
3631     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3632     if (buf == NULL) {
3633         xmlErrMemory(ctxt, NULL);
3634         return(NULL);
3635     }
3636
3637     /*
3638      * The content of the entity definition is copied in a buffer.
3639      */
3640
3641     ctxt->instate = XML_PARSER_ENTITY_VALUE;
3642     input = ctxt->input;
3643     GROW;
3644     NEXT;
3645     c = CUR_CHAR(l);
3646     /*
3647      * NOTE: 4.4.5 Included in Literal
3648      * When a parameter entity reference appears in a literal entity
3649      * value, ... a single or double quote character in the replacement
3650      * text is always treated as a normal data character and will not
3651      * terminate the literal. 
3652      * In practice it means we stop the loop only when back at parsing
3653      * the initial entity and the quote is found
3654      */
3655     while ((IS_CHAR(c)) && ((c != stop) || /* checked */
3656            (ctxt->input != input))) {
3657         if (len + 5 >= size) {
3658             xmlChar *tmp;
3659
3660             size *= 2;
3661             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
3662             if (tmp == NULL) {
3663                 xmlErrMemory(ctxt, NULL);
3664                 xmlFree(buf);
3665                 return(NULL);
3666             }
3667             buf = tmp;
3668         }
3669         COPY_BUF(l,buf,len,c);
3670         NEXTL(l);
3671         /*
3672          * Pop-up of finished entities.
3673          */
3674         while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
3675             xmlPopInput(ctxt);
3676
3677         GROW;
3678         c = CUR_CHAR(l);
3679         if (c == 0) {
3680             GROW;
3681             c = CUR_CHAR(l);
3682         }
3683     }
3684     buf[len] = 0;
3685
3686     /*
3687      * Raise problem w.r.t. '&' and '%' being used in non-entities
3688      * reference constructs. Note Charref will be handled in
3689      * xmlStringDecodeEntities()
3690      */
3691     cur = buf;
3692     while (*cur != 0) { /* non input consuming */
3693         if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3694             xmlChar *name;
3695             xmlChar tmp = *cur;
3696
3697             cur++;
3698             name = xmlParseStringName(ctxt, &cur);
3699             if ((name == NULL) || (*cur != ';')) {
3700                 xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3701             "EntityValue: '%c' forbidden except for entities references\n",
3702                                   tmp);
3703             }
3704             if ((tmp == '%') && (ctxt->inSubset == 1) &&
3705                 (ctxt->inputNr == 1)) {
3706                 xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3707             }
3708             if (name != NULL)
3709                 xmlFree(name);
3710             if (*cur == 0)
3711                 break;
3712         }
3713         cur++;
3714     }
3715
3716     /*
3717      * Then PEReference entities are substituted.
3718      */
3719     if (c != stop) {
3720         xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3721         xmlFree(buf);
3722     } else {
3723         NEXT;
3724         /*
3725          * NOTE: 4.4.7 Bypassed
3726          * When a general entity reference appears in the EntityValue in
3727          * an entity declaration, it is bypassed and left as is.
3728          * so XML_SUBSTITUTE_REF is not set here.
3729          */
3730         ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3731                                       0, 0, 0);
3732         if (orig != NULL) 
3733             *orig = buf;
3734         else
3735             xmlFree(buf);
3736     }
3737     
3738     return(ret);
3739 }
3740
3741 /**
3742  * xmlParseAttValueComplex:
3743  * @ctxt:  an XML parser context
3744  * @len:   the resulting attribute len
3745  * @normalize:  wether to apply the inner normalization
3746  *
3747  * parse a value for an attribute, this is the fallback function
3748  * of xmlParseAttValue() when the attribute parsing requires handling
3749  * of non-ASCII characters, or normalization compaction.
3750  *
3751  * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3752  */
3753 static xmlChar *
3754 xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3755     xmlChar limit = 0;
3756     xmlChar *buf = NULL;
3757     xmlChar *rep = NULL;
3758     int len = 0;
3759     int buf_size = 0;
3760     int c, l, in_space = 0;
3761     xmlChar *current = NULL;
3762     xmlEntityPtr ent;
3763
3764     if (NXT(0) == '"') {
3765         ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3766         limit = '"';
3767         NEXT;
3768     } else if (NXT(0) == '\'') {
3769         limit = '\'';
3770         ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3771         NEXT;
3772     } else {
3773         xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3774         return(NULL);
3775     }
3776
3777     /*
3778      * allocate a translation buffer.
3779      */
3780     buf_size = XML_PARSER_BUFFER_SIZE;
3781     buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
3782     if (buf == NULL) goto mem_error;
3783
3784     /*
3785      * OK loop until we reach one of the ending char or a size limit.
3786      */
3787     c = CUR_CHAR(l);
3788     while ((NXT(0) != limit) && /* checked */
3789            (IS_CHAR(c)) && (c != '<')) {
3790         if (c == 0) break;
3791         if (c == '&') {
3792             in_space = 0;
3793             if (NXT(1) == '#') {
3794                 int val = xmlParseCharRef(ctxt);
3795
3796                 if (val == '&') {
3797                     if (ctxt->replaceEntities) {
3798                         if (len > buf_size - 10) {
3799                             growBuffer(buf, 10);
3800                         }
3801                         buf[len++] = '&';
3802                     } else {
3803                         /*
3804                          * The reparsing will be done in xmlStringGetNodeList()
3805                          * called by the attribute() function in SAX.c
3806                          */
3807                         if (len > buf_size - 10) {
3808                             growBuffer(buf, 10);
3809                         }
3810                         buf[len++] = '&';
3811                         buf[len++] = '#';
3812                         buf[len++] = '3';
3813                         buf[len++] = '8';
3814                         buf[len++] = ';';
3815                     }
3816                 } else if (val != 0) {
3817                     if (len > buf_size - 10) {
3818                         growBuffer(buf, 10);
3819                     }
3820                     len += xmlCopyChar(0, &buf[len], val);
3821                 }
3822             } else {
3823                 ent = xmlParseEntityRef(ctxt);
3824                 ctxt->nbentities++;
3825                 if (ent != NULL)
3826                     ctxt->nbentities += ent->owner;
3827                 if ((ent != NULL) &&
3828                     (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
3829                     if (len > buf_size - 10) {
3830                         growBuffer(buf, 10);
3831                     }
3832                     if ((ctxt->replaceEntities == 0) &&
3833                         (ent->content[0] == '&')) {
3834                         buf[len++] = '&';
3835                         buf[len++] = '#';
3836                         buf[len++] = '3';
3837                         buf[len++] = '8';
3838                         buf[len++] = ';';
3839                     } else {
3840                         buf[len++] = ent->content[0];
3841                     }
3842                 } else if ((ent != NULL) && 
3843                            (ctxt->replaceEntities != 0)) {
3844                     if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
3845                         rep = xmlStringDecodeEntities(ctxt, ent->content,
3846                                                       XML_SUBSTITUTE_REF,
3847                                                       0, 0, 0);
3848                         if (rep != NULL) {
3849                             current = rep;
3850                             while (*current != 0) { /* non input consuming */
3851                                 if ((*current == 0xD) || (*current == 0xA) ||
3852                                     (*current == 0x9)) {
3853                                     buf[len++] = 0x20;
3854                                     current++;
3855                                 } else
3856                                     buf[len++] = *current++;
3857                                 if (len > buf_size - 10) {
3858                                     growBuffer(buf, 10);
3859                                 }
3860                             }
3861                             xmlFree(rep);
3862                             rep = NULL;
3863                         }
3864                     } else {
3865                         if (len > buf_size - 10) {
3866                             growBuffer(buf, 10);
3867                         }
3868                         if (ent->content != NULL)
3869                             buf[len++] = ent->content[0];
3870                     }
3871                 } else if (ent != NULL) {
3872                     int i = xmlStrlen(ent->name);
3873                     const xmlChar *cur = ent->name;
3874
3875                     /*
3876                      * This may look absurd but is needed to detect
3877                      * entities problems
3878                      */
3879                     if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
3880                         (ent->content != NULL)) {
3881                         rep = xmlStringDecodeEntities(ctxt, ent->content,
3882                                                   XML_SUBSTITUTE_REF, 0, 0, 0);
3883                         if (rep != NULL) {
3884                             xmlFree(rep);
3885                             rep = NULL;
3886                         }
3887                     }
3888
3889                     /*
3890                      * Just output the reference
3891                      */
3892                     buf[len++] = '&';
3893                     while (len > buf_size - i - 10) {
3894                         growBuffer(buf, i + 10);
3895                     }
3896                     for (;i > 0;i--)
3897                         buf[len++] = *cur++;
3898                     buf[len++] = ';';
3899                 }
3900             }
3901         } else {
3902             if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
3903                 if ((len != 0) || (!normalize)) {
3904                     if ((!normalize) || (!in_space)) {
3905                         COPY_BUF(l,buf,len,0x20);
3906                         while (len > buf_size - 10) {
3907                             growBuffer(buf, 10);
3908                         }
3909                     }
3910                     in_space = 1;
3911                 }
3912             } else {
3913                 in_space = 0;
3914                 COPY_BUF(l,buf,len,c);
3915                 if (len > buf_size - 10) {
3916                     growBuffer(buf, 10);
3917                 }
3918             }
3919             NEXTL(l);
3920         }
3921         GROW;
3922         c = CUR_CHAR(l);
3923     }
3924     if ((in_space) && (normalize)) {
3925         while (buf[len - 1] == 0x20) len--;
3926     }
3927     buf[len] = 0;
3928     if (RAW == '<') {
3929         xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
3930     } else if (RAW != limit) {
3931         if ((c != 0) && (!IS_CHAR(c))) {
3932             xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
3933                            "invalid character in attribute value\n");
3934         } else {
3935             xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
3936                            "AttValue: ' expected\n");
3937         }
3938     } else
3939         NEXT;
3940     if (attlen != NULL) *attlen = len;
3941     return(buf);
3942
3943 mem_error:
3944     xmlErrMemory(ctxt, NULL);
3945     if (buf != NULL)
3946         xmlFree(buf);
3947     if (rep != NULL)
3948         xmlFree(rep);
3949     return(NULL);
3950 }
3951
3952 /**
3953  * xmlParseAttValue:
3954  * @ctxt:  an XML parser context
3955  *
3956  * parse a value for an attribute
3957  * Note: the parser won't do substitution of entities here, this
3958  * will be handled later in xmlStringGetNodeList
3959  *
3960  * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
3961  *                   "'" ([^<&'] | Reference)* "'"
3962  *
3963  * 3.3.3 Attribute-Value Normalization:
3964  * Before the value of an attribute is passed to the application or
3965  * checked for validity, the XML processor must normalize it as follows: 
3966  * - a character reference is processed by appending the referenced
3967  *   character to the attribute value
3968  * - an entity reference is processed by recursively processing the
3969  *   replacement text of the entity 
3970  * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
3971  *   appending #x20 to the normalized value, except that only a single
3972  *   #x20 is appended for a "#xD#xA" sequence that is part of an external
3973  *   parsed entity or the literal entity value of an internal parsed entity 
3974  * - other characters are processed by appending them to the normalized value 
3975  * If the declared value is not CDATA, then the XML processor must further
3976  * process the normalized attribute value by discarding any leading and
3977  * trailing space (#x20) characters, and by replacing sequences of space
3978  * (#x20) characters by a single space (#x20) character.  
3979  * All attributes for which no declaration has been read should be treated
3980  * by a non-validating parser as if declared CDATA.
3981  *
3982  * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3983  */
3984
3985
3986 xmlChar *
3987 xmlParseAttValue(xmlParserCtxtPtr ctxt) {
3988     if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
3989     return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
3990 }
3991
3992 /**
3993  * xmlParseSystemLiteral:
3994  * @ctxt:  an XML parser context
3995  * 
3996  * parse an XML Literal
3997  *
3998  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
3999  *
4000  * Returns the SystemLiteral parsed or NULL
4001  */
4002
4003 xmlChar *
4004 xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4005     xmlChar *buf = NULL;
4006     int len = 0;
4007     int size = XML_PARSER_BUFFER_SIZE;
4008     int cur, l;
4009     xmlChar stop;
4010     int state = ctxt->instate;
4011     int count = 0;
4012
4013     SHRINK;
4014     if (RAW == '"') {
4015         NEXT;
4016         stop = '"';
4017     } else if (RAW == '\'') {
4018         NEXT;
4019         stop = '\'';
4020     } else {
4021         xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4022         return(NULL);
4023     }
4024     
4025     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4026     if (buf == NULL) {
4027         xmlErrMemory(ctxt, NULL);
4028         return(NULL);
4029     }
4030     ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4031     cur = CUR_CHAR(l);
4032     while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4033         if (len + 5 >= size) {
4034             xmlChar *tmp;
4035
4036             size *= 2;
4037             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4038             if (tmp == NULL) {
4039                 xmlFree(buf);
4040                 xmlErrMemory(ctxt, NULL);
4041                 ctxt->instate = (xmlParserInputState) state;
4042                 return(NULL);
4043             }
4044             buf = tmp;
4045         }
4046         count++;
4047         if (count > 50) {
4048             GROW;
4049             count = 0;
4050         }
4051         COPY_BUF(l,buf,len,cur);
4052         NEXTL(l);
4053         cur = CUR_CHAR(l);
4054         if (cur == 0) {
4055             GROW;
4056             SHRINK;
4057             cur = CUR_CHAR(l);
4058         }
4059     }
4060     buf[len] = 0;
4061     ctxt->instate = (xmlParserInputState) state;
4062     if (!IS_CHAR(cur)) {
4063         xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4064     } else {
4065         NEXT;
4066     }
4067     return(buf);
4068 }
4069
4070 /**
4071  * xmlParsePubidLiteral:
4072  * @ctxt:  an XML parser context
4073  *
4074  * parse an XML public literal
4075  *
4076  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4077  *
4078  * Returns the PubidLiteral parsed or NULL.
4079  */
4080
4081 xmlChar *
4082 xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4083     xmlChar *buf = NULL;
4084     int len = 0;
4085     int size = XML_PARSER_BUFFER_SIZE;
4086     xmlChar cur;
4087     xmlChar stop;
4088     int count = 0;
4089     xmlParserInputState oldstate = ctxt->instate;
4090
4091     SHRINK;
4092     if (RAW == '"') {
4093         NEXT;
4094         stop = '"';
4095     } else if (RAW == '\'') {
4096         NEXT;
4097         stop = '\'';
4098     } else {
4099         xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4100         return(NULL);
4101     }
4102     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4103     if (buf == NULL) {
4104         xmlErrMemory(ctxt, NULL);
4105         return(NULL);
4106     }
4107     ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4108     cur = CUR;
4109     while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4110         if (len + 1 >= size) {
4111             xmlChar *tmp;
4112
4113             size *= 2;
4114             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4115             if (tmp == NULL) {
4116                 xmlErrMemory(ctxt, NULL);
4117                 xmlFree(buf);
4118                 return(NULL);
4119             }
4120             buf = tmp;
4121         }
4122         buf[len++] = cur;
4123         count++;
4124         if (count > 50) {
4125             GROW;
4126             count = 0;
4127         }
4128         NEXT;
4129         cur = CUR;
4130         if (cur == 0) {
4131             GROW;
4132             SHRINK;
4133             cur = CUR;
4134         }
4135     }
4136     buf[len] = 0;
4137     if (cur != stop) {
4138         xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4139     } else {
4140         NEXT;
4141     }
4142     ctxt->instate = oldstate;
4143     return(buf);
4144 }
4145
4146 static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
4147
4148 /*
4149  * used for the test in the inner loop of the char data testing
4150  */
4151 static const unsigned char test_char_data[256] = {
4152     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4153     0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4154     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4155     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4156     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4157     0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4158     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4159     0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4160     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4161     0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4162     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4163     0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4164     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4165     0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4166     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4167     0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4168     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4169     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4170     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4171     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4172     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4173     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4174     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4175     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4176     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4177     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4178     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4179     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4180     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4181     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4182     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4183     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4184 };
4185
4186 /**
4187  * xmlParseCharData:
4188  * @ctxt:  an XML parser context
4189  * @cdata:  int indicating whether we are within a CDATA section
4190  *
4191  * parse a CharData section.
4192  * if we are within a CDATA section ']]>' marks an end of section.
4193  *
4194  * The right angle bracket (>) may be represented using the string "&gt;",
4195  * and must, for compatibility, be escaped using "&gt;" or a character
4196  * reference when it appears in the string "]]>" in content, when that
4197  * string is not marking the end of a CDATA section. 
4198  *
4199  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4200  */
4201
4202 void
4203 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
4204     const xmlChar *in;
4205     int nbchar = 0;
4206     int line = ctxt->input->line;
4207     int col = ctxt->input->col;
4208     int ccol;
4209
4210     SHRINK;
4211     GROW;
4212     /*
4213      * Accelerated common case where input don't need to be
4214      * modified before passing it to the handler.
4215      */
4216     if (!cdata) {
4217         in = ctxt->input->cur;
4218         do {
4219 get_more_space:
4220             while (*in == 0x20) { in++; ctxt->input->col++; }
4221             if (*in == 0xA) {
4222                 do {
4223                     ctxt->input->line++; ctxt->input->col = 1;
4224                     in++;
4225                 } while (*in == 0xA);
4226                 goto get_more_space;
4227             }
4228             if (*in == '<') {
4229                 nbchar = in - ctxt->input->cur;
4230                 if (nbchar > 0) {
4231                     const xmlChar *tmp = ctxt->input->cur;
4232                     ctxt->input->cur = in;
4233
4234                     if ((ctxt->sax != NULL) &&
4235                         (ctxt->sax->ignorableWhitespace !=
4236                          ctxt->sax->characters)) {
4237                         if (areBlanks(ctxt, tmp, nbchar, 1)) {
4238                             if (ctxt->sax->ignorableWhitespace != NULL)
4239                                 ctxt->sax->ignorableWhitespace(ctxt->userData,
4240                                                        tmp, nbchar);
4241                         } else {
4242                             if (ctxt->sax->characters != NULL)
4243                                 ctxt->sax->characters(ctxt->userData,
4244                                                       tmp, nbchar);
4245                             if (*ctxt->space == -1)
4246                                 *ctxt->space = -2;
4247                         }
4248                     } else if ((ctxt->sax != NULL) &&
4249                                (ctxt->sax->characters != NULL)) {
4250                         ctxt->sax->characters(ctxt->userData,
4251                                               tmp, nbchar);
4252                     }
4253                 }
4254                 return;
4255             }
4256
4257 get_more:
4258             ccol = ctxt->input->col;
4259             while (test_char_data[*in]) {
4260                 in++;
4261                 ccol++;
4262             }
4263             ctxt->input->col = ccol;
4264             if (*in == 0xA) {
4265                 do {
4266                     ctxt->input->line++; ctxt->input->col = 1;
4267                     in++;
4268                 } while (*in == 0xA);
4269                 goto get_more;
4270             }
4271             if (*in == ']') {
4272                 if ((in[1] == ']') && (in[2] == '>')) {
4273                     xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4274                     ctxt->input->cur = in;
4275                     return;
4276                 }
4277                 in++;
4278                 ctxt->input->col++;
4279                 goto get_more;
4280             }
4281             nbchar = in - ctxt->input->cur;
4282             if (nbchar > 0) {
4283                 if ((ctxt->sax != NULL) &&
4284                     (ctxt->sax->ignorableWhitespace !=
4285                      ctxt->sax->characters) &&
4286                     (IS_BLANK_CH(*ctxt->input->cur))) {
4287                     const xmlChar *tmp = ctxt->input->cur;
4288                     ctxt->input->cur = in;
4289
4290                     if (areBlanks(ctxt, tmp, nbchar, 0)) {
4291                         if (ctxt->sax->ignorableWhitespace != NULL)
4292                             ctxt->sax->ignorableWhitespace(ctxt->userData,
4293                                                            tmp, nbchar);
4294                     } else {
4295                         if (ctxt->sax->characters != NULL)
4296                             ctxt->sax->characters(ctxt->userData,
4297                                                   tmp, nbchar);
4298                         if (*ctxt->space == -1)
4299                             *ctxt->space = -2;
4300                     }
4301                     line = ctxt->input->line;
4302                     col = ctxt->input->col;
4303                 } else if (ctxt->sax != NULL) {
4304                     if (ctxt->sax->characters != NULL)
4305                         ctxt->sax->characters(ctxt->userData,
4306                                               ctxt->input->cur, nbchar);
4307                     line = ctxt->input->line;
4308                     col = ctxt->input->col;
4309                 }
4310                 /* something really bad happened in the SAX callback */
4311                 if (ctxt->instate != XML_PARSER_CONTENT)
4312                     return;
4313             }
4314             ctxt->input->cur = in;
4315             if (*in == 0xD) {
4316                 in++;
4317                 if (*in == 0xA) {
4318                     ctxt->input->cur = in;
4319                     in++;
4320                     ctxt->input->line++; ctxt->input->col = 1;
4321                     continue; /* while */
4322                 }
4323                 in--;
4324             }
4325             if (*in == '<') {
4326                 return;
4327             }
4328             if (*in == '&') {
4329                 return;
4330             }
4331             SHRINK;
4332             GROW;
4333             in = ctxt->input->cur;
4334         } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
4335         nbchar = 0;
4336     }
4337     ctxt->input->line = line;
4338     ctxt->input->col = col;
4339     xmlParseCharDataComplex(ctxt, cdata);
4340 }
4341
4342 /**
4343  * xmlParseCharDataComplex:
4344  * @ctxt:  an XML parser context
4345  * @cdata:  int indicating whether we are within a CDATA section
4346  *
4347  * parse a CharData section.this is the fallback function
4348  * of xmlParseCharData() when the parsing requires handling
4349  * of non-ASCII characters.
4350  */
4351 static void
4352 xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
4353     xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4354     int nbchar = 0;
4355     int cur, l;
4356     int count = 0;
4357
4358     SHRINK;
4359     GROW;
4360     cur = CUR_CHAR(l);
4361     while ((cur != '<') && /* checked */
4362            (cur != '&') && 
4363            (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4364         if ((cur == ']') && (NXT(1) == ']') &&
4365             (NXT(2) == '>')) {
4366             if (cdata) break;
4367             else {
4368                 xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4369             }
4370         }
4371         COPY_BUF(l,buf,nbchar,cur);
4372         if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4373             buf[nbchar] = 0;
4374
4375             /*
4376              * OK the segment is to be consumed as chars.
4377              */
4378             if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4379                 if (areBlanks(ctxt, buf, nbchar, 0)) {
4380                     if (ctxt->sax->ignorableWhitespace != NULL)
4381                         ctxt->sax->ignorableWhitespace(ctxt->userData,
4382                                                        buf, nbchar);
4383                 } else {
4384                     if (ctxt->sax->characters != NULL)
4385                         ctxt->sax->characters(ctxt->userData, buf, nbchar);
4386                     if ((ctxt->sax->characters !=
4387                          ctxt->sax->ignorableWhitespace) &&
4388                         (*ctxt->space == -1))
4389                         *ctxt->space = -2;
4390                 }
4391             }
4392             nbchar = 0;
4393             /* something really bad happened in the SAX callback */
4394             if (ctxt->instate != XML_PARSER_CONTENT)
4395                 return;
4396         }
4397         count++;
4398         if (count > 50) {
4399             GROW;
4400             count = 0;
4401         }
4402         NEXTL(l);
4403         cur = CUR_CHAR(l);
4404     }
4405     if (nbchar != 0) {
4406         buf[nbchar] = 0;
4407         /*
4408          * OK the segment is to be consumed as chars.
4409          */
4410         if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4411             if (areBlanks(ctxt, buf, nbchar, 0)) {
4412                 if (ctxt->sax->ignorableWhitespace != NULL)
4413                     ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4414             } else {
4415                 if (ctxt->sax->characters != NULL)
4416                     ctxt->sax->characters(ctxt->userData, buf, nbchar);
4417                 if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4418                     (*ctxt->space == -1))
4419                     *ctxt->space = -2;
4420             }
4421         }
4422     }
4423     if ((cur != 0) && (!IS_CHAR(cur))) {
4424         /* Generate the error and skip the offending character */
4425         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4426                           "PCDATA invalid Char value %d\n",
4427                           cur);
4428         NEXTL(l);
4429     }
4430 }
4431
4432 /**
4433  * xmlParseExternalID:
4434  * @ctxt:  an XML parser context
4435  * @publicID:  a xmlChar** receiving PubidLiteral
4436  * @strict: indicate whether we should restrict parsing to only
4437  *          production [75], see NOTE below
4438  *
4439  * Parse an External ID or a Public ID
4440  *
4441  * NOTE: Productions [75] and [83] interact badly since [75] can generate
4442  *       'PUBLIC' S PubidLiteral S SystemLiteral
4443  *
4444  * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4445  *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4446  *
4447  * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4448  *
4449  * Returns the function returns SystemLiteral and in the second
4450  *                case publicID receives PubidLiteral, is strict is off
4451  *                it is possible to return NULL and have publicID set.
4452  */
4453
4454 xmlChar *
4455 xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4456     xmlChar *URI = NULL;
4457
4458     SHRINK;
4459
4460     *publicID = NULL;
4461     if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4462         SKIP(6);
4463         if (!IS_BLANK_CH(CUR)) {
4464             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4465                            "Space required after 'SYSTEM'\n");
4466         }
4467         SKIP_BLANKS;
4468         URI = xmlParseSystemLiteral(ctxt);
4469         if (URI == NULL) {
4470             xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4471         }
4472     } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4473         SKIP(6);
4474         if (!IS_BLANK_CH(CUR)) {
4475             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4476                     "Space required after 'PUBLIC'\n");
4477         }
4478         SKIP_BLANKS;
4479         *publicID = xmlParsePubidLiteral(ctxt);
4480         if (*publicID == NULL) {
4481             xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4482         }
4483         if (strict) {
4484             /*
4485              * We don't handle [83] so "S SystemLiteral" is required.
4486              */
4487             if (!IS_BLANK_CH(CUR)) {
4488                 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4489                         "Space required after the Public Identifier\n");
4490             }
4491         } else {
4492             /*
4493              * We handle [83] so we return immediately, if 
4494              * "S SystemLiteral" is not detected. From a purely parsing
4495              * point of view that's a nice mess.
4496              */
4497             const xmlChar *ptr;
4498             GROW;
4499
4500             ptr = CUR_PTR;
4501             if (!IS_BLANK_CH(*ptr)) return(NULL);
4502             
4503             while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
4504             if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
4505         }
4506         SKIP_BLANKS;
4507         URI = xmlParseSystemLiteral(ctxt);
4508         if (URI == NULL) {
4509             xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4510         }
4511     }
4512     return(URI);
4513 }
4514
4515 /**
4516  * xmlParseCommentComplex:
4517  * @ctxt:  an XML parser context
4518  * @buf:  the already parsed part of the buffer
4519  * @len:  number of bytes filles in the buffer
4520  * @size:  allocated size of the buffer
4521  *
4522  * Skip an XML (SGML) comment <!-- .... -->
4523  *  The spec says that "For compatibility, the string "--" (double-hyphen)
4524  *  must not occur within comments. "
4525  * This is the slow routine in case the accelerator for ascii didn't work
4526  *
4527  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4528  */
4529 static void
4530 xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) {
4531     int q, ql;
4532     int r, rl;
4533     int cur, l;
4534     int count = 0;
4535     int inputid;
4536
4537     inputid = ctxt->input->id;
4538
4539     if (buf == NULL) {
4540         len = 0;
4541         size = XML_PARSER_BUFFER_SIZE;
4542         buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4543         if (buf == NULL) {
4544             xmlErrMemory(ctxt, NULL);
4545             return;
4546         }
4547     }
4548     GROW;       /* Assure there's enough input data */
4549     q = CUR_CHAR(ql);
4550     if (q == 0)
4551         goto not_terminated;
4552     if (!IS_CHAR(q)) {
4553         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4554                           "xmlParseComment: invalid xmlChar value %d\n",
4555                           q);
4556         xmlFree (buf);
4557         return;
4558     }
4559     NEXTL(ql);
4560     r = CUR_CHAR(rl);
4561     if (r == 0)
4562         goto not_terminated;
4563     if (!IS_CHAR(r)) {
4564         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4565                           "xmlParseComment: invalid xmlChar value %d\n",
4566                           q);
4567         xmlFree (buf);
4568         return;
4569     }
4570     NEXTL(rl);
4571     cur = CUR_CHAR(l);
4572     if (cur == 0)
4573         goto not_terminated;
4574     while (IS_CHAR(cur) && /* checked */
4575            ((cur != '>') ||
4576             (r != '-') || (q != '-'))) {
4577         if ((r == '-') && (q == '-')) {
4578             xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4579         }
4580         if (len + 5 >= size) {
4581             xmlChar *new_buf;
4582             size *= 2;
4583             new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4584             if (new_buf == NULL) {
4585                 xmlFree (buf);
4586                 xmlErrMemory(ctxt, NULL);
4587                 return;
4588             }
4589             buf = new_buf;
4590         }
4591         COPY_BUF(ql,buf,len,q);
4592         q = r;
4593         ql = rl;
4594         r = cur;
4595         rl = l;
4596
4597         count++;
4598         if (count > 50) {
4599             GROW;
4600             count = 0;
4601         }
4602         NEXTL(l);
4603         cur = CUR_CHAR(l);
4604         if (cur == 0) {
4605             SHRINK;
4606             GROW;
4607             cur = CUR_CHAR(l);
4608         }
4609     }
4610     buf[len] = 0;
4611     if (cur == 0) {
4612         xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4613                              "Comment not terminated \n<!--%.50s\n", buf);
4614     } else if (!IS_CHAR(cur)) {
4615         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4616                           "xmlParseComment: invalid xmlChar value %d\n",
4617                           cur);
4618     } else {
4619         if (inputid != ctxt->input->id) {
4620             xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4621                 "Comment doesn't start and stop in the same entity\n");
4622         }
4623         NEXT;
4624         if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4625             (!ctxt->disableSAX))
4626             ctxt->sax->comment(ctxt->userData, buf);
4627     }
4628     xmlFree(buf);
4629     return;
4630 not_terminated:
4631     xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4632                          "Comment not terminated\n", NULL);
4633     xmlFree(buf);
4634     return;
4635 }
4636
4637 /**
4638  * xmlParseComment:
4639  * @ctxt:  an XML parser context
4640  *
4641  * Skip an XML (SGML) comment <!-- .... -->
4642  *  The spec says that "For compatibility, the string "--" (double-hyphen)
4643  *  must not occur within comments. "
4644  *
4645  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4646  */
4647 void
4648 xmlParseComment(xmlParserCtxtPtr ctxt) {
4649     xmlChar *buf = NULL;
4650     int size = XML_PARSER_BUFFER_SIZE;
4651     int len = 0;
4652     xmlParserInputState state;
4653     const xmlChar *in;
4654     int nbchar = 0, ccol;
4655     int inputid;
4656
4657     /*
4658      * Check that there is a comment right here.
4659      */
4660     if ((RAW != '<') || (NXT(1) != '!') ||
4661         (NXT(2) != '-') || (NXT(3) != '-')) return;
4662     state = ctxt->instate;
4663     ctxt->instate = XML_PARSER_COMMENT;
4664     inputid = ctxt->input->id;
4665     SKIP(4);
4666     SHRINK;
4667     GROW;
4668
4669     /*
4670      * Accelerated common case where input don't need to be
4671      * modified before passing it to the handler.
4672      */
4673     in = ctxt->input->cur;
4674     do {
4675         if (*in == 0xA) {
4676             do {
4677                 ctxt->input->line++; ctxt->input->col = 1;
4678                 in++;
4679             } while (*in == 0xA);
4680         }
4681 get_more:
4682         ccol = ctxt->input->col;
4683         while (((*in > '-') && (*in <= 0x7F)) ||
4684                ((*in >= 0x20) && (*in < '-')) ||
4685                (*in == 0x09)) {
4686                     in++;
4687                     ccol++;
4688         }
4689         ctxt->input->col = ccol;
4690         if (*in == 0xA) {
4691             do {
4692                 ctxt->input->line++; ctxt->input->col = 1;
4693                 in++;
4694             } while (*in == 0xA);
4695             goto get_more;
4696         }
4697         nbchar = in - ctxt->input->cur;
4698         /*
4699          * save current set of data
4700          */
4701         if (nbchar > 0) {
4702             if ((ctxt->sax != NULL) &&
4703                 (ctxt->sax->comment != NULL)) {
4704                 if (buf == NULL) {
4705                     if ((*in == '-') && (in[1] == '-'))
4706                         size = nbchar + 1;
4707                     else
4708                         size = XML_PARSER_BUFFER_SIZE + nbchar;
4709                     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4710                     if (buf == NULL) {
4711                         xmlErrMemory(ctxt, NULL);
4712                         ctxt->instate = state;
4713                         return;
4714                     }
4715                     len = 0;
4716                 } else if (len + nbchar + 1 >= size) {
4717                     xmlChar *new_buf;
4718                     size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
4719                     new_buf = (xmlChar *) xmlRealloc(buf,
4720                                                      size * sizeof(xmlChar));
4721                     if (new_buf == NULL) {
4722                         xmlFree (buf);
4723                         xmlErrMemory(ctxt, NULL);
4724                         ctxt->instate = state;
4725                         return;
4726                     }
4727                     buf = new_buf;
4728                 }
4729                 memcpy(&buf[len], ctxt->input->cur, nbchar);
4730                 len += nbchar;
4731                 buf[len] = 0;
4732             }
4733         }
4734         ctxt->input->cur = in;
4735         if (*in == 0xA) {
4736             in++;
4737             ctxt->input->line++; ctxt->input->col = 1;
4738         }
4739         if (*in == 0xD) {
4740             in++;
4741             if (*in == 0xA) {
4742                 ctxt->input->cur = in;
4743                 in++;
4744                 ctxt->input->line++; ctxt->input->col = 1;
4745                 continue; /* while */
4746             }
4747             in--;
4748         }
4749         SHRINK;
4750         GROW;
4751         in = ctxt->input->cur;
4752         if (*in == '-') {
4753             if (in[1] == '-') {
4754                 if (in[2] == '>') {
4755                     if (ctxt->input->id != inputid) {
4756                         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4757                         "comment doesn't start and stop in the same entity\n");
4758                     }
4759                     SKIP(3);
4760                     if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4761                         (!ctxt->disableSAX)) {
4762                         if (buf != NULL)
4763                             ctxt->sax->comment(ctxt->userData, buf);
4764                         else
4765                             ctxt->sax->comment(ctxt->userData, BAD_CAST "");
4766                     }
4767                     if (buf != NULL)
4768                         xmlFree(buf);
4769                     ctxt->instate = state;
4770                     return;
4771                 }
4772                 if (buf != NULL)
4773                     xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4774                                       "Comment not terminated \n<!--%.50s\n",
4775                                       buf);
4776                 else
4777                     xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4778                                       "Comment not terminated \n", NULL);
4779                 in++;
4780                 ctxt->input->col++;
4781             }
4782             in++;
4783             ctxt->input->col++;
4784             goto get_more;
4785         }
4786     } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
4787     xmlParseCommentComplex(ctxt, buf, len, size);
4788     ctxt->instate = state;
4789     return;
4790 }
4791
4792
4793 /**
4794  * xmlParsePITarget:
4795  * @ctxt:  an XML parser context
4796  * 
4797  * parse the name of a PI
4798  *
4799  * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
4800  *
4801  * Returns the PITarget name or NULL
4802  */
4803
4804 const xmlChar *
4805 xmlParsePITarget(xmlParserCtxtPtr ctxt) {
4806     const xmlChar *name;
4807
4808     name = xmlParseName(ctxt);
4809     if ((name != NULL) &&
4810         ((name[0] == 'x') || (name[0] == 'X')) &&
4811         ((name[1] == 'm') || (name[1] == 'M')) &&
4812         ((name[2] == 'l') || (name[2] == 'L'))) {
4813         int i;
4814         if ((name[0] == 'x') && (name[1] == 'm') &&
4815             (name[2] == 'l') && (name[3] == 0)) {
4816             xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
4817                  "XML declaration allowed only at the start of the document\n");
4818             return(name);
4819         } else if (name[3] == 0) {
4820             xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
4821             return(name);
4822         }
4823         for (i = 0;;i++) {
4824             if (xmlW3CPIs[i] == NULL) break;
4825             if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
4826                 return(name);
4827         }
4828         xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
4829                       "xmlParsePITarget: invalid name prefix 'xml'\n",
4830                       NULL, NULL);
4831     }
4832     if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
4833         xmlNsErr(ctxt, XML_NS_ERR_COLON, 
4834                  "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
4835     }
4836     return(name);
4837 }
4838
4839 #ifdef LIBXML_CATALOG_ENABLED
4840 /**
4841  * xmlParseCatalogPI:
4842  * @ctxt:  an XML parser context
4843  * @catalog:  the PI value string
4844  * 
4845  * parse an XML Catalog Processing Instruction.
4846  *
4847  * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
4848  *
4849  * Occurs only if allowed by the user and if happening in the Misc
4850  * part of the document before any doctype informations
4851  * This will add the given catalog to the parsing context in order
4852  * to be used if there is a resolution need further down in the document
4853  */
4854
4855 static void
4856 xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
4857     xmlChar *URL = NULL;
4858     const xmlChar *tmp, *base;
4859     xmlChar marker;
4860
4861     tmp = catalog;
4862     while (IS_BLANK_CH(*tmp)) tmp++;
4863     if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
4864         goto error;
4865     tmp += 7;
4866     while (IS_BLANK_CH(*tmp)) tmp++;
4867     if (*tmp != '=') {
4868         return;
4869     }
4870     tmp++;
4871     while (IS_BLANK_CH(*tmp)) tmp++;
4872     marker = *tmp;
4873     if ((marker != '\'') && (marker != '"'))
4874         goto error;
4875     tmp++;
4876     base = tmp;
4877     while ((*tmp != 0) && (*tmp != marker)) tmp++;
4878     if (*tmp == 0)
4879         goto error;
4880     URL = xmlStrndup(base, tmp - base);
4881     tmp++;
4882     while (IS_BLANK_CH(*tmp)) tmp++;
4883     if (*tmp != 0)
4884         goto error;
4885
4886     if (URL != NULL) {
4887         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
4888         xmlFree(URL);
4889     }
4890     return;
4891
4892 error:
4893     xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
4894                   "Catalog PI syntax error: %s\n",
4895                   catalog, NULL);
4896     if (URL != NULL)
4897         xmlFree(URL);
4898 }
4899 #endif
4900
4901 /**
4902  * xmlParsePI:
4903  * @ctxt:  an XML parser context
4904  * 
4905  * parse an XML Processing Instruction.
4906  *
4907  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
4908  *
4909  * The processing is transfered to SAX once parsed.
4910  */
4911
4912 void
4913 xmlParsePI(xmlParserCtxtPtr ctxt) {
4914     xmlChar *buf = NULL;
4915     int len = 0;
4916     int size = XML_PARSER_BUFFER_SIZE;
4917     int cur, l;
4918     const xmlChar *target;
4919     xmlParserInputState state;
4920     int count = 0;
4921
4922     if ((RAW == '<') && (NXT(1) == '?')) {
4923         xmlParserInputPtr input = ctxt->input;
4924         state = ctxt->instate;
4925         ctxt->instate = XML_PARSER_PI;
4926         /*
4927          * this is a Processing Instruction.
4928          */
4929         SKIP(2);
4930         SHRINK;
4931
4932         /*
4933          * Parse the target name and check for special support like
4934          * namespace.
4935          */
4936         target = xmlParsePITarget(ctxt);
4937         if (target != NULL) {
4938             if ((RAW == '?') && (NXT(1) == '>')) {
4939                 if (input != ctxt->input) {
4940                     xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4941             "PI declaration doesn't start and stop in the same entity\n");
4942                 }
4943                 SKIP(2);
4944
4945                 /*
4946                  * SAX: PI detected.
4947                  */
4948                 if ((ctxt->sax) && (!ctxt->disableSAX) &&
4949                     (ctxt->sax->processingInstruction != NULL))
4950                     ctxt->sax->processingInstruction(ctxt->userData,
4951                                                      target, NULL);
4952                 ctxt->instate = state;
4953                 return;
4954             }
4955             buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4956             if (buf == NULL) {
4957                 xmlErrMemory(ctxt, NULL);
4958                 ctxt->instate = state;
4959                 return;
4960             }
4961             cur = CUR;
4962             if (!IS_BLANK(cur)) {
4963                 xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
4964                           "ParsePI: PI %s space expected\n", target);
4965             }
4966             SKIP_BLANKS;
4967             cur = CUR_CHAR(l);
4968             while (IS_CHAR(cur) && /* checked */
4969                    ((cur != '?') || (NXT(1) != '>'))) {
4970                 if (len + 5 >= size) {
4971                     xmlChar *tmp;
4972
4973                     size *= 2;
4974                     tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4975                     if (tmp == NULL) {
4976                         xmlErrMemory(ctxt, NULL);
4977                         xmlFree(buf);
4978                         ctxt->instate = state;
4979                         return;
4980                     }
4981                     buf = tmp;
4982                 }
4983                 count++;
4984                 if (count > 50) {
4985                     GROW;
4986                     count = 0;
4987                 }
4988                 COPY_BUF(l,buf,len,cur);
4989                 NEXTL(l);
4990                 cur = CUR_CHAR(l);
4991                 if (cur == 0) {
4992                     SHRINK;
4993                     GROW;
4994                     cur = CUR_CHAR(l);
4995                 }
4996             }
4997             buf[len] = 0;
4998             if (cur != '?') {
4999                 xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5000                       "ParsePI: PI %s never end ...\n", target);
5001             } else {
5002                 if (input != ctxt->input) {
5003                     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5004             "PI declaration doesn't start and stop in the same entity\n");
5005                 }
5006                 SKIP(2);
5007
5008 #ifdef LIBXML_CATALOG_ENABLED
5009                 if (((state == XML_PARSER_MISC) ||
5010                      (state == XML_PARSER_START)) &&
5011                     (xmlStrEqual(target, XML_CATALOG_PI))) {
5012                     xmlCatalogAllow allow = xmlCatalogGetDefaults();
5013                     if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5014                         (allow == XML_CATA_ALLOW_ALL))
5015                         xmlParseCatalogPI(ctxt, buf);
5016                 }
5017 #endif
5018
5019
5020                 /*
5021                  * SAX: PI detected.
5022                  */
5023                 if ((ctxt->sax) && (!ctxt->disableSAX) &&
5024                     (ctxt->sax->processingInstruction != NULL))
5025                     ctxt->sax->processingInstruction(ctxt->userData,
5026                                                      target, buf);
5027             }
5028             xmlFree(buf);
5029         } else {
5030             xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5031         }
5032         ctxt->instate = state;
5033     }
5034 }
5035
5036 /**
5037  * xmlParseNotationDecl:
5038  * @ctxt:  an XML parser context
5039  *
5040  * parse a notation declaration
5041  *
5042  * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5043  *
5044  * Hence there is actually 3 choices:
5045  *     'PUBLIC' S PubidLiteral
5046  *     'PUBLIC' S PubidLiteral S SystemLiteral
5047  * and 'SYSTEM' S SystemLiteral
5048  *
5049  * See the NOTE on xmlParseExternalID().
5050  */
5051
5052 void
5053 xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5054     const xmlChar *name;
5055     xmlChar *Pubid;
5056     xmlChar *Systemid;
5057     
5058     if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5059         xmlParserInputPtr input = ctxt->input;
5060         SHRINK;
5061         SKIP(10);
5062         if (!IS_BLANK_CH(CUR)) {
5063             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5064                            "Space required after '<!NOTATION'\n");
5065             return;
5066         }
5067         SKIP_BLANKS;
5068
5069         name = xmlParseName(ctxt);
5070         if (name == NULL) {
5071             xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5072             return;
5073         }
5074         if (!IS_BLANK_CH(CUR)) {
5075             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5076                      "Space required after the NOTATION name'\n");
5077             return;
5078         }
5079         if (xmlStrchr(name, ':') != NULL) {
5080             xmlNsErr(ctxt, XML_NS_ERR_COLON, 
5081                      "colon are forbidden from notation names '%s'\n",
5082                      name, NULL, NULL);
5083         }
5084         SKIP_BLANKS;
5085
5086         /*
5087          * Parse the IDs.
5088          */
5089         Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5090         SKIP_BLANKS;
5091
5092         if (RAW == '>') {
5093             if (input != ctxt->input) {
5094                 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5095         "Notation declaration doesn't start and stop in the same entity\n");
5096             }
5097             NEXT;
5098             if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5099                 (ctxt->sax->notationDecl != NULL))
5100                 ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5101         } else {
5102             xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5103         }
5104         if (Systemid != NULL) xmlFree(Systemid);
5105         if (Pubid != NULL) xmlFree(Pubid);
5106     }
5107 }
5108
5109 /**
5110  * xmlParseEntityDecl:
5111  * @ctxt:  an XML parser context
5112  *
5113  * parse <!ENTITY declarations
5114  *
5115  * [70] EntityDecl ::= GEDecl | PEDecl
5116  *
5117  * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5118  *
5119  * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5120  *
5121  * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5122  *
5123  * [74] PEDef ::= EntityValue | ExternalID
5124  *
5125  * [76] NDataDecl ::= S 'NDATA' S Name
5126  *
5127  * [ VC: Notation Declared ]
5128  * The Name must match the declared name of a notation.
5129  */
5130
5131 void
5132 xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5133     const xmlChar *name = NULL;
5134     xmlChar *value = NULL;
5135     xmlChar *URI = NULL, *literal = NULL;
5136     const xmlChar *ndata = NULL;
5137     int isParameter = 0;
5138     xmlChar *orig = NULL;
5139     int skipped;
5140     
5141     /* GROW; done in the caller */
5142     if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
5143         xmlParserInputPtr input = ctxt->input;
5144         SHRINK;
5145         SKIP(8);
5146         skipped = SKIP_BLANKS;
5147         if (skipped == 0) {
5148             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5149                            "Space required after '<!ENTITY'\n");
5150         }
5151
5152         if (RAW == '%') {
5153             NEXT;
5154             skipped = SKIP_BLANKS;
5155             if (skipped == 0) {
5156                 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5157                                "Space required after '%'\n");
5158             }
5159             isParameter = 1;
5160         }
5161
5162         name = xmlParseName(ctxt);
5163         if (name == NULL) {
5164             xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5165                            "xmlParseEntityDecl: no name\n");
5166             return;
5167         }
5168         if (xmlStrchr(name, ':') != NULL) {
5169             xmlNsErr(ctxt, XML_NS_ERR_COLON, 
5170                      "colon are forbidden from entities names '%s'\n",
5171                      name, NULL, NULL);
5172         }
5173         skipped = SKIP_BLANKS;
5174         if (skipped == 0) {
5175             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5176                            "Space required after the entity name\n");
5177         }
5178
5179         ctxt->instate = XML_PARSER_ENTITY_DECL;
5180         /*
5181          * handle the various case of definitions...
5182          */
5183         if (isParameter) {
5184             if ((RAW == '"') || (RAW == '\'')) {
5185                 value = xmlParseEntityValue(ctxt, &orig);
5186                 if (value) {
5187                     if ((ctxt->sax != NULL) &&
5188                         (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5189                         ctxt->sax->entityDecl(ctxt->userData, name,
5190                                     XML_INTERNAL_PARAMETER_ENTITY,
5191                                     NULL, NULL, value);
5192                 }
5193             } else {
5194                 URI = xmlParseExternalID(ctxt, &literal, 1);
5195                 if ((URI == NULL) && (literal == NULL)) {
5196                     xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5197                 }
5198                 if (URI) {
5199                     xmlURIPtr uri;
5200
5201                     uri = xmlParseURI((const char *) URI);
5202                     if (uri == NULL) {
5203                         xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5204                                      "Invalid URI: %s\n", URI);
5205                         /*
5206                          * This really ought to be a well formedness error
5207                          * but the XML Core WG decided otherwise c.f. issue
5208                          * E26 of the XML erratas.
5209                          */
5210                     } else {
5211                         if (uri->fragment != NULL) {
5212                             /*
5213                              * Okay this is foolish to block those but not
5214                              * invalid URIs.
5215                              */
5216                             xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5217                         } else {
5218                             if ((ctxt->sax != NULL) &&
5219                                 (!ctxt->disableSAX) &&
5220                                 (ctxt->sax->entityDecl != NULL))
5221                                 ctxt->sax->entityDecl(ctxt->userData, name,
5222                                             XML_EXTERNAL_PARAMETER_ENTITY,
5223                                             literal, URI, NULL);
5224                         }
5225                         xmlFreeURI(uri);
5226                     }
5227                 }
5228             }
5229         } else {
5230             if ((RAW == '"') || (RAW == '\'')) {
5231                 value = xmlParseEntityValue(ctxt, &orig);
5232                 if ((ctxt->sax != NULL) &&
5233                     (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5234                     ctxt->sax->entityDecl(ctxt->userData, name,
5235                                 XML_INTERNAL_GENERAL_ENTITY,
5236                                 NULL, NULL, value);
5237                 /*
5238                  * For expat compatibility in SAX mode.
5239                  */
5240                 if ((ctxt->myDoc == NULL) ||
5241                     (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5242                     if (ctxt->myDoc == NULL) {
5243                         ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5244                         if (ctxt->myDoc == NULL) {
5245                             xmlErrMemory(ctxt, "New Doc failed");
5246                             return;
5247                         }
5248                         ctxt->myDoc->properties = XML_DOC_INTERNAL;
5249                     }
5250                     if (ctxt->myDoc->intSubset == NULL)
5251                         ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5252                                             BAD_CAST "fake", NULL, NULL);
5253
5254                     xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5255                                       NULL, NULL, value);
5256                 }
5257             } else {
5258                 URI = xmlParseExternalID(ctxt, &literal, 1);
5259                 if ((URI == NULL) && (literal == NULL)) {
5260                     xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5261                 }
5262                 if (URI) {
5263                     xmlURIPtr uri;
5264
5265                     uri = xmlParseURI((const char *)URI);
5266                     if (uri == NULL) {
5267                         xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5268                                      "Invalid URI: %s\n", URI);
5269                         /*
5270                          * This really ought to be a well formedness error
5271                          * but the XML Core WG decided otherwise c.f. issue
5272                          * E26 of the XML erratas.
5273                          */
5274                     } else {
5275                         if (uri->fragment != NULL) {
5276                             /*
5277                              * Okay this is foolish to block those but not
5278                              * invalid URIs.
5279                              */
5280                             xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5281                         }
5282                         xmlFreeURI(uri);
5283                     }
5284                 }
5285                 if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
5286                     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5287                                    "Space required before 'NDATA'\n");
5288                 }
5289                 SKIP_BLANKS;
5290                 if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5291                     SKIP(5);
5292                     if (!IS_BLANK_CH(CUR)) {
5293                         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5294                                        "Space required after 'NDATA'\n");
5295                     }
5296                     SKIP_BLANKS;
5297                     ndata = xmlParseName(ctxt);
5298                     if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5299                         (ctxt->sax->unparsedEntityDecl != NULL))
5300                         ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5301                                     literal, URI, ndata);
5302                 } else {
5303                     if ((ctxt->sax != NULL) &&
5304                         (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5305                         ctxt->sax->entityDecl(ctxt->userData, name,
5306                                     XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5307                                     literal, URI, NULL);
5308                     /*
5309                      * For expat compatibility in SAX mode.
5310                      * assuming the entity repalcement was asked for
5311                      */
5312                     if ((ctxt->replaceEntities != 0) &&
5313                         ((ctxt->myDoc == NULL) ||
5314                         (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5315                         if (ctxt->myDoc == NULL) {
5316                             ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5317                             if (ctxt->myDoc == NULL) {
5318                                 xmlErrMemory(ctxt, "New Doc failed");
5319                                 return;
5320                             }
5321                             ctxt->myDoc->properties = XML_DOC_INTERNAL;
5322                         }
5323
5324                         if (ctxt->myDoc->intSubset == NULL)
5325                             ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5326                                                 BAD_CAST "fake", NULL, NULL);
5327                         xmlSAX2EntityDecl(ctxt, name,
5328                                           XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5329                                           literal, URI, NULL);
5330                     }
5331                 }
5332             }
5333         }
5334         SKIP_BLANKS;
5335         if (RAW != '>') {
5336             xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5337                     "xmlParseEntityDecl: entity %s not terminated\n", name);
5338         } else {
5339             if (input != ctxt->input) {
5340                 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5341         "Entity declaration doesn't start and stop in the same entity\n");
5342             }
5343             NEXT;
5344         }
5345         if (orig != NULL) {
5346             /*
5347              * Ugly mechanism to save the raw entity value.
5348              */
5349             xmlEntityPtr cur = NULL;
5350
5351             if (isParameter) {
5352                 if ((ctxt->sax != NULL) &&
5353                     (ctxt->sax->getParameterEntity != NULL))
5354                     cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5355             } else {
5356                 if ((ctxt->sax != NULL) &&
5357                     (ctxt->sax->getEntity != NULL))
5358                     cur = ctxt->sax->getEntity(ctxt->userData, name);
5359                 if ((cur == NULL) && (ctxt->userData==ctxt)) {
5360                     cur = xmlSAX2GetEntity(ctxt, name);
5361                 }
5362             }
5363             if (cur != NULL) {
5364                 if (cur->orig != NULL)
5365                     xmlFree(orig);
5366                 else
5367                     cur->orig = orig;
5368             } else
5369                 xmlFree(orig);
5370         }
5371         if (value != NULL) xmlFree(value);
5372         if (URI != NULL) xmlFree(URI);
5373         if (literal != NULL) xmlFree(literal);
5374     }
5375 }
5376
5377 /**
5378  * xmlParseDefaultDecl:
5379  * @ctxt:  an XML parser context
5380  * @value:  Receive a possible fixed default value for the attribute
5381  *
5382  * Parse an attribute default declaration
5383  *
5384  * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5385  *
5386  * [ VC: Required Attribute ]
5387  * if the default declaration is the keyword #REQUIRED, then the
5388  * attribute must be specified for all elements of the type in the
5389  * attribute-list declaration.
5390  *
5391  * [ VC: Attribute Default Legal ]
5392  * The declared default value must meet the lexical constraints of
5393  * the declared attribute type c.f. xmlValidateAttributeDecl()
5394  *
5395  * [ VC: Fixed Attribute Default ]
5396  * if an attribute has a default value declared with the #FIXED
5397  * keyword, instances of that attribute must match the default value. 
5398  *
5399  * [ WFC: No < in Attribute Values ]
5400  * handled in xmlParseAttValue()
5401  *
5402  * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5403  *          or XML_ATTRIBUTE_FIXED. 
5404  */
5405
5406 int
5407 xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5408     int val;
5409     xmlChar *ret;
5410
5411     *value = NULL;
5412     if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5413         SKIP(9);
5414         return(XML_ATTRIBUTE_REQUIRED);
5415     }
5416     if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5417         SKIP(8);
5418         return(XML_ATTRIBUTE_IMPLIED);
5419     }
5420     val = XML_ATTRIBUTE_NONE;
5421     if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5422         SKIP(6);
5423         val = XML_ATTRIBUTE_FIXED;
5424         if (!IS_BLANK_CH(CUR)) {
5425             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5426                            "Space required after '#FIXED'\n");
5427         }
5428         SKIP_BLANKS;
5429     }
5430     ret = xmlParseAttValue(ctxt);
5431     ctxt->instate = XML_PARSER_DTD;
5432     if (ret == NULL) {
5433         xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5434                        "Attribute default value declaration error\n");
5435     } else
5436         *value = ret;
5437     return(val);
5438 }
5439
5440 /**
5441  * xmlParseNotationType:
5442  * @ctxt:  an XML parser context
5443  *
5444  * parse an Notation attribute type.
5445  *
5446  * Note: the leading 'NOTATION' S part has already being parsed...
5447  *
5448  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5449  *
5450  * [ VC: Notation Attributes ]
5451  * Values of this type must match one of the notation names included
5452  * in the declaration; all notation names in the declaration must be declared. 
5453  *
5454  * Returns: the notation attribute tree built while parsing
5455  */
5456
5457 xmlEnumerationPtr
5458 xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5459     const xmlChar *name;
5460     xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5461
5462     if (RAW != '(') {
5463         xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5464         return(NULL);
5465     }
5466     SHRINK;
5467     do {
5468         NEXT;
5469         SKIP_BLANKS;
5470         name = xmlParseName(ctxt);
5471         if (name == NULL) {
5472             xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5473                            "Name expected in NOTATION declaration\n");
5474             xmlFreeEnumeration(ret);
5475             return(NULL);
5476         }
5477         tmp = ret;
5478         while (tmp != NULL) {
5479             if (xmlStrEqual(name, tmp->name)) {
5480                 xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5481           "standalone: attribute notation value token %s duplicated\n",
5482                                  name, NULL);
5483                 if (!xmlDictOwns(ctxt->dict, name))
5484                     xmlFree((xmlChar *) name);
5485                 break;
5486             }
5487             tmp = tmp->next;
5488         }
5489         if (tmp == NULL) {
5490             cur = xmlCreateEnumeration(name);
5491             if (cur == NULL) {
5492                 xmlFreeEnumeration(ret);
5493                 return(NULL);
5494             }
5495             if (last == NULL) ret = last = cur;
5496             else {
5497                 last->next = cur;
5498                 last = cur;
5499             }
5500         }
5501         SKIP_BLANKS;
5502     } while (RAW == '|');
5503     if (RAW != ')') {
5504         xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5505         xmlFreeEnumeration(ret);
5506         return(NULL);
5507     }
5508     NEXT;
5509     return(ret);
5510 }
5511
5512 /**
5513  * xmlParseEnumerationType:
5514  * @ctxt:  an XML parser context
5515  *
5516  * parse an Enumeration attribute type.
5517  *
5518  * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5519  *
5520  * [ VC: Enumeration ]
5521  * Values of this type must match one of the Nmtoken tokens in
5522  * the declaration
5523  *
5524  * Returns: the enumeration attribute tree built while parsing
5525  */
5526
5527 xmlEnumerationPtr
5528 xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5529     xmlChar *name;
5530     xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5531
5532     if (RAW != '(') {
5533         xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5534         return(NULL);
5535     }
5536     SHRINK;
5537     do {
5538         NEXT;
5539         SKIP_BLANKS;
5540         name = xmlParseNmtoken(ctxt);
5541         if (name == NULL) {
5542             xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5543             return(ret);
5544         }
5545         tmp = ret;
5546         while (tmp != NULL) {
5547             if (xmlStrEqual(name, tmp->name)) {
5548                 xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5549           "standalone: attribute enumeration value token %s duplicated\n",
5550                                  name, NULL);
5551                 if (!xmlDictOwns(ctxt->dict, name))
5552                     xmlFree(name);
5553                 break;
5554             }
5555             tmp = tmp->next;
5556         }
5557         if (tmp == NULL) {
5558             cur = xmlCreateEnumeration(name);
5559             if (!xmlDictOwns(ctxt->dict, name))
5560                 xmlFree(name);
5561             if (cur == NULL) {
5562                 xmlFreeEnumeration(ret);
5563                 return(NULL);
5564             }
5565             if (last == NULL) ret = last = cur;
5566             else {
5567                 last->next = cur;
5568                 last = cur;
5569             }
5570         }
5571         SKIP_BLANKS;
5572     } while (RAW == '|');
5573     if (RAW != ')') {
5574         xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5575         return(ret);
5576     }
5577     NEXT;
5578     return(ret);
5579 }
5580
5581 /**
5582  * xmlParseEnumeratedType:
5583  * @ctxt:  an XML parser context
5584  * @tree:  the enumeration tree built while parsing
5585  *
5586  * parse an Enumerated attribute type.
5587  *
5588  * [57] EnumeratedType ::= NotationType | Enumeration
5589  *
5590  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5591  *
5592  *
5593  * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5594  */
5595
5596 int
5597 xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5598     if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5599         SKIP(8);
5600         if (!IS_BLANK_CH(CUR)) {
5601             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5602                            "Space required after 'NOTATION'\n");
5603             return(0);
5604         }
5605         SKIP_BLANKS;
5606         *tree = xmlParseNotationType(ctxt);
5607         if (*tree == NULL) return(0);
5608         return(XML_ATTRIBUTE_NOTATION);
5609     }
5610     *tree = xmlParseEnumerationType(ctxt);
5611     if (*tree == NULL) return(0);
5612     return(XML_ATTRIBUTE_ENUMERATION);
5613 }
5614
5615 /**
5616  * xmlParseAttributeType:
5617  * @ctxt:  an XML parser context
5618  * @tree:  the enumeration tree built while parsing
5619  *
5620  * parse the Attribute list def for an element
5621  *
5622  * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5623  *
5624  * [55] StringType ::= 'CDATA'
5625  *
5626  * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5627  *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5628  *
5629  * Validity constraints for attribute values syntax are checked in
5630  * xmlValidateAttributeValue()
5631  *
5632  * [ VC: ID ]
5633  * Values of type ID must match the Name production. A name must not
5634  * appear more than once in an XML document as a value of this type;
5635  * i.e., ID values must uniquely identify the elements which bear them.
5636  *
5637  * [ VC: One ID per Element Type ]
5638  * No element type may have more than one ID attribute specified.
5639  *
5640  * [ VC: ID Attribute Default ]
5641  * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5642  *
5643  * [ VC: IDREF ]
5644  * Values of type IDREF must match the Name production, and values
5645  * of type IDREFS must match Names; each IDREF Name must match the value
5646  * of an ID attribute on some element in the XML document; i.e. IDREF
5647  * values must match the value of some ID attribute.
5648  *
5649  * [ VC: Entity Name ]
5650  * Values of type ENTITY must match the Name production, values
5651  * of type ENTITIES must match Names; each Entity Name must match the
5652  * name of an unparsed entity declared in the DTD.  
5653  *
5654  * [ VC: Name Token ]
5655  * Values of type NMTOKEN must match the Nmtoken production; values
5656  * of type NMTOKENS must match Nmtokens. 
5657  *
5658  * Returns the attribute type
5659  */
5660 int 
5661 xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5662     SHRINK;
5663     if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
5664         SKIP(5);
5665         return(XML_ATTRIBUTE_CDATA);
5666      } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
5667         SKIP(6);
5668         return(XML_ATTRIBUTE_IDREFS);
5669      } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
5670         SKIP(5);
5671         return(XML_ATTRIBUTE_IDREF);
5672      } else if ((RAW == 'I') && (NXT(1) == 'D')) {
5673         SKIP(2);
5674         return(XML_ATTRIBUTE_ID);
5675      } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5676         SKIP(6);
5677         return(XML_ATTRIBUTE_ENTITY);
5678      } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
5679         SKIP(8);
5680         return(XML_ATTRIBUTE_ENTITIES);
5681      } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
5682         SKIP(8);
5683         return(XML_ATTRIBUTE_NMTOKENS);
5684      } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
5685         SKIP(7);
5686         return(XML_ATTRIBUTE_NMTOKEN);
5687      }
5688      return(xmlParseEnumeratedType(ctxt, tree));
5689 }
5690
5691 /**
5692  * xmlParseAttributeListDecl:
5693  * @ctxt:  an XML parser context
5694  *
5695  * : parse the Attribute list def for an element
5696  *
5697  * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
5698  *
5699  * [53] AttDef ::= S Name S AttType S DefaultDecl
5700  *
5701  */
5702 void
5703 xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
5704     const xmlChar *elemName;
5705     const xmlChar *attrName;
5706     xmlEnumerationPtr tree;
5707
5708     if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
5709         xmlParserInputPtr input = ctxt->input;
5710
5711         SKIP(9);
5712         if (!IS_BLANK_CH(CUR)) {
5713             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5714                                  "Space required after '<!ATTLIST'\n");
5715         }
5716         SKIP_BLANKS;
5717         elemName = xmlParseName(ctxt);
5718         if (elemName == NULL) {
5719             xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5720                            "ATTLIST: no name for Element\n");
5721             return;
5722         }
5723         SKIP_BLANKS;
5724         GROW;
5725         while (RAW != '>') {
5726             const xmlChar *check = CUR_PTR;
5727             int type;
5728             int def;
5729             xmlChar *defaultValue = NULL;
5730
5731             GROW;
5732             tree = NULL;
5733             attrName = xmlParseName(ctxt);
5734             if (attrName == NULL) {
5735                 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5736                                "ATTLIST: no name for Attribute\n");
5737                 break;
5738             }
5739             GROW;
5740             if (!IS_BLANK_CH(CUR)) {
5741                 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5742                         "Space required after the attribute name\n");
5743                 break;
5744             }
5745             SKIP_BLANKS;
5746
5747             type = xmlParseAttributeType(ctxt, &tree);
5748             if (type <= 0) {
5749                 break;
5750             }
5751
5752             GROW;
5753             if (!IS_BLANK_CH(CUR)) {
5754                 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5755                                "Space required after the attribute type\n");
5756                 if (tree != NULL)
5757                     xmlFreeEnumeration(tree);
5758                 break;
5759             }
5760             SKIP_BLANKS;
5761
5762             def = xmlParseDefaultDecl(ctxt, &defaultValue);
5763             if (def <= 0) {
5764                 if (defaultValue != NULL)
5765                     xmlFree(defaultValue);
5766                 if (tree != NULL)
5767                     xmlFreeEnumeration(tree);
5768                 break;
5769             }
5770             if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
5771                 xmlAttrNormalizeSpace(defaultValue, defaultValue);
5772
5773             GROW;
5774             if (RAW != '>') {
5775                 if (!IS_BLANK_CH(CUR)) {
5776                     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5777                         "Space required after the attribute default value\n");
5778                     if (defaultValue != NULL)
5779                         xmlFree(defaultValue);
5780                     if (tree != NULL)
5781                         xmlFreeEnumeration(tree);
5782                     break;
5783                 }
5784                 SKIP_BLANKS;
5785             }
5786             if (check == CUR_PTR) {
5787                 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
5788                             "in xmlParseAttributeListDecl\n");
5789                 if (defaultValue != NULL)
5790                     xmlFree(defaultValue);
5791                 if (tree != NULL)
5792                     xmlFreeEnumeration(tree);
5793                 break;
5794             }
5795             if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5796                 (ctxt->sax->attributeDecl != NULL))
5797                 ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
5798                                 type, def, defaultValue, tree);
5799             else if (tree != NULL)
5800                 xmlFreeEnumeration(tree);
5801
5802             if ((ctxt->sax2) && (defaultValue != NULL) &&
5803                 (def != XML_ATTRIBUTE_IMPLIED) && 
5804                 (def != XML_ATTRIBUTE_REQUIRED)) {
5805                 xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
5806             }
5807             if (ctxt->sax2) {
5808                 xmlAddSpecialAttr(ctxt, elemName, attrName, type);
5809             }
5810             if (defaultValue != NULL)
5811                 xmlFree(defaultValue);
5812             GROW;
5813         }
5814         if (RAW == '>') {
5815             if (input != ctxt->input) {
5816                 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
5817     "Attribute list declaration doesn't start and stop in the same entity\n",
5818                                  NULL, NULL);
5819             }
5820             NEXT;
5821         }
5822     }
5823 }
5824
5825 /**
5826  * xmlParseElementMixedContentDecl:
5827  * @ctxt:  an XML parser context
5828  * @inputchk:  the input used for the current entity, needed for boundary checks
5829  *
5830  * parse the declaration for a Mixed Element content
5831  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
5832  * 
5833  * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
5834  *                '(' S? '#PCDATA' S? ')'
5835  *
5836  * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
5837  *
5838  * [ VC: No Duplicate Types ]
5839  * The same name must not appear more than once in a single
5840  * mixed-content declaration. 
5841  *
5842  * returns: the list of the xmlElementContentPtr describing the element choices
5843  */
5844 xmlElementContentPtr
5845 xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
5846     xmlElementContentPtr ret = NULL, cur = NULL, n;
5847     const xmlChar *elem = NULL;
5848
5849     GROW;
5850     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
5851         SKIP(7);
5852         SKIP_BLANKS;
5853         SHRINK;
5854         if (RAW == ')') {
5855             if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
5856                 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
5857 "Element content declaration doesn't start and stop in the same entity\n",
5858                                  NULL, NULL);
5859             }
5860             NEXT;
5861             ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
5862             if (ret == NULL)
5863                 return(NULL);
5864             if (RAW == '*') {
5865                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
5866                 NEXT;
5867             }
5868             return(ret);
5869         }
5870         if ((RAW == '(') || (RAW == '|')) {
5871             ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
5872             if (ret == NULL) return(NULL);
5873         }
5874         while (RAW == '|') {
5875             NEXT;
5876             if (elem == NULL) {
5877                 ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
5878                 if (ret == NULL) return(NULL);
5879                 ret->c1 = cur;
5880                 if (cur != NULL)
5881                     cur->parent = ret;
5882                 cur = ret;
5883             } else {
5884                 n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
5885                 if (n == NULL) return(NULL);
5886                 n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
5887                 if (n->c1 != NULL)
5888                     n->c1->parent = n;
5889                 cur->c2 = n;
5890                 if (n != NULL)
5891                     n->parent = cur;
5892                 cur = n;
5893             }
5894             SKIP_BLANKS;
5895             elem = xmlParseName(ctxt);
5896             if (elem == NULL) {
5897                 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5898                         "xmlParseElementMixedContentDecl : Name expected\n");
5899                 xmlFreeDocElementContent(ctxt->myDoc, cur);
5900                 return(NULL);
5901             }
5902             SKIP_BLANKS;
5903             GROW;
5904         }
5905         if ((RAW == ')') && (NXT(1) == '*')) {
5906             if (elem != NULL) {
5907                 cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
5908                                                XML_ELEMENT_CONTENT_ELEMENT);
5909                 if (cur->c2 != NULL)
5910                     cur->c2->parent = cur;
5911             }
5912             if (ret != NULL)
5913                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
5914             if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
5915                 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
5916 "Element content declaration doesn't start and stop in the same entity\n",
5917                                  NULL, NULL);
5918             }
5919             SKIP(2);
5920         } else {
5921             xmlFreeDocElementContent(ctxt->myDoc, ret);
5922             xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
5923             return(NULL);
5924         }
5925
5926     } else {
5927         xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
5928     }
5929     return(ret);
5930 }
5931
5932 /**
5933  * xmlParseElementChildrenContentDeclPriv:
5934  * @ctxt:  an XML parser context
5935  * @inputchk:  the input used for the current entity, needed for boundary checks
5936  * @depth: the level of recursion
5937  *
5938  * parse the declaration for a Mixed Element content
5939  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
5940  * 
5941  *
5942  * [47] children ::= (choice | seq) ('?' | '*' | '+')?
5943  *
5944  * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
5945  *
5946  * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
5947  *
5948  * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
5949  *
5950  * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
5951  * TODO Parameter-entity replacement text must be properly nested
5952  *      with parenthesized groups. That is to say, if either of the
5953  *      opening or closing parentheses in a choice, seq, or Mixed
5954  *      construct is contained in the replacement text for a parameter
5955  *      entity, both must be contained in the same replacement text. For
5956  *      interoperability, if a parameter-entity reference appears in a
5957  *      choice, seq, or Mixed construct, its replacement text should not
5958  *      be empty, and neither the first nor last non-blank character of
5959  *      the replacement text should be a connector (| or ,).
5960  *
5961  * Returns the tree of xmlElementContentPtr describing the element 
5962  *          hierarchy.
5963  */
5964 static xmlElementContentPtr
5965 xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
5966                                        int depth) {
5967     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
5968     const xmlChar *elem;
5969     xmlChar type = 0;
5970
5971     if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
5972         (depth >  2048)) {
5973         xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
5974 "xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
5975                           depth);
5976         return(NULL);
5977     }
5978     SKIP_BLANKS;
5979     GROW;
5980     if (RAW == '(') {
5981         int inputid = ctxt->input->id;
5982
5983         /* Recurse on first child */
5984         NEXT;
5985         SKIP_BLANKS;
5986         cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
5987                                                            depth + 1);
5988         SKIP_BLANKS;
5989         GROW;
5990     } else {
5991         elem = xmlParseName(ctxt);
5992         if (elem == NULL) {
5993             xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
5994             return(NULL);
5995         }
5996         cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
5997         if (cur == NULL) {
5998             xmlErrMemory(ctxt, NULL);
5999             return(NULL);
6000         }
6001         GROW;
6002         if (RAW == '?') {
6003             cur->ocur = XML_ELEMENT_CONTENT_OPT;
6004             NEXT;
6005         } else if (RAW == '*') {
6006             cur->ocur = XML_ELEMENT_CONTENT_MULT;
6007             NEXT;
6008         } else if (RAW == '+') {
6009             cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6010             NEXT;
6011         } else {
6012             cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6013         }
6014         GROW;
6015     }
6016     SKIP_BLANKS;
6017     SHRINK;
6018     while (RAW != ')') {
6019         /*
6020          * Each loop we parse one separator and one element.
6021          */
6022         if (RAW == ',') {
6023             if (type == 0) type = CUR;
6024
6025             /*
6026              * Detect "Name | Name , Name" error
6027              */
6028             else if (type != CUR) {
6029                 xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6030                     "xmlParseElementChildrenContentDecl : '%c' expected\n",
6031                                   type);
6032                 if ((last != NULL) && (last != ret))
6033                     xmlFreeDocElementContent(ctxt->myDoc, last);
6034                 if (ret != NULL)
6035                     xmlFreeDocElementContent(ctxt->myDoc, ret);
6036                 return(NULL);
6037             }
6038             NEXT;
6039
6040             op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6041             if (op == NULL) {
6042                 if ((last != NULL) && (last != ret))
6043                     xmlFreeDocElementContent(ctxt->myDoc, last);
6044                 xmlFreeDocElementContent(ctxt->myDoc, ret);
6045                 return(NULL);
6046             }
6047             if (last == NULL) {
6048                 op->c1 = ret;
6049                 if (ret != NULL)
6050                     ret->parent = op;
6051                 ret = cur = op;
6052             } else {
6053                 cur->c2 = op;
6054                 if (op != NULL)
6055                     op->parent = cur;
6056                 op->c1 = last;
6057                 if (last != NULL)
6058                     last->parent = op;
6059                 cur =op;
6060                 last = NULL;
6061             }
6062         } else if (RAW == '|') {
6063             if (type == 0) type = CUR;
6064
6065             /*
6066              * Detect "Name , Name | Name" error
6067              */
6068             else if (type != CUR) {
6069                 xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6070                     "xmlParseElementChildrenContentDecl : '%c' expected\n",
6071                                   type);
6072                 if ((last != NULL) && (last != ret))
6073                     xmlFreeDocElementContent(ctxt->myDoc, last);
6074                 if (ret != NULL)
6075                     xmlFreeDocElementContent(ctxt->myDoc, ret);
6076                 return(NULL);
6077             }
6078             NEXT;
6079
6080             op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6081             if (op == NULL) {
6082                 if ((last != NULL) && (last != ret))
6083                     xmlFreeDocElementContent(ctxt->myDoc, last);
6084                 if (ret != NULL)
6085                     xmlFreeDocElementContent(ctxt->myDoc, ret);
6086                 return(NULL);
6087             }
6088             if (last == NULL) {
6089                 op->c1 = ret;
6090                 if (ret != NULL)
6091                     ret->parent = op;
6092                 ret = cur = op;
6093             } else {
6094                 cur->c2 = op;
6095                 if (op != NULL)
6096                     op->parent = cur;
6097                 op->c1 = last;
6098                 if (last != NULL)
6099                     last->parent = op;
6100                 cur =op;
6101                 last = NULL;
6102             }
6103         } else {
6104             xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6105             if ((last != NULL) && (last != ret))
6106                 xmlFreeDocElementContent(ctxt->myDoc, last);
6107             if (ret != NULL)
6108                 xmlFreeDocElementContent(ctxt->myDoc, ret);
6109             return(NULL);
6110         }
6111         GROW;
6112         SKIP_BLANKS;
6113         GROW;
6114         if (RAW == '(') {
6115             int inputid = ctxt->input->id;
6116             /* Recurse on second child */
6117             NEXT;
6118             SKIP_BLANKS;
6119             last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6120                                                           depth + 1);
6121             SKIP_BLANKS;
6122         } else {
6123             elem = xmlParseName(ctxt);
6124             if (elem == NULL) {
6125                 xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6126                 if (ret != NULL)
6127                     xmlFreeDocElementContent(ctxt->myDoc, ret);
6128                 return(NULL);
6129             }
6130             last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6131             if (last == NULL) {
6132                 if (ret != NULL)
6133                     xmlFreeDocElementContent(ctxt->myDoc, ret);
6134                 return(NULL);
6135             }
6136             if (RAW == '?') {
6137                 last->ocur = XML_ELEMENT_CONTENT_OPT;
6138                 NEXT;
6139             } else if (RAW == '*') {
6140                 last->ocur = XML_ELEMENT_CONTENT_MULT;
6141                 NEXT;
6142             } else if (RAW == '+') {
6143                 last->ocur = XML_ELEMENT_CONTENT_PLUS;
6144                 NEXT;
6145             } else {
6146                 last->ocur = XML_ELEMENT_CONTENT_ONCE;
6147             }
6148         }
6149         SKIP_BLANKS;
6150         GROW;
6151     }
6152     if ((cur != NULL) && (last != NULL)) {
6153         cur->c2 = last;
6154         if (last != NULL)
6155             last->parent = cur;
6156     }
6157     if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6158         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6159 "Element content declaration doesn't start and stop in the same entity\n",
6160                          NULL, NULL);
6161     }
6162     NEXT;
6163     if (RAW == '?') {
6164         if (ret != NULL) {
6165             if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6166                 (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6167                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
6168             else
6169                 ret->ocur = XML_ELEMENT_CONTENT_OPT;
6170         }
6171         NEXT;
6172     } else if (RAW == '*') {
6173         if (ret != NULL) {
6174             ret->ocur = XML_ELEMENT_CONTENT_MULT;
6175             cur = ret;
6176             /*
6177              * Some normalization:
6178              * (a | b* | c?)* == (a | b | c)*
6179              */
6180             while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6181                 if ((cur->c1 != NULL) &&
6182                     ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6183                      (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6184                     cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6185                 if ((cur->c2 != NULL) &&
6186                     ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6187                      (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6188                     cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6189                 cur = cur->c2;
6190             }
6191         }
6192         NEXT;
6193     } else if (RAW == '+') {
6194         if (ret != NULL) {
6195             int found = 0;
6196
6197             if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6198                 (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6199                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
6200             else
6201                 ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6202             /*
6203              * Some normalization:
6204              * (a | b*)+ == (a | b)*
6205              * (a | b?)+ == (a | b)*
6206              */
6207             while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6208                 if ((cur->c1 != NULL) &&
6209                     ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6210                      (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6211                     cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6212                     found = 1;
6213                 }
6214                 if ((cur->c2 != NULL) &&
6215                     ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6216                      (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6217                     cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6218                     found = 1;
6219                 }
6220                 cur = cur->c2;
6221             }
6222             if (found)
6223                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
6224         }
6225         NEXT;
6226     }
6227     return(ret);
6228 }
6229
6230 /**
6231  * xmlParseElementChildrenContentDecl:
6232  * @ctxt:  an XML parser context
6233  * @inputchk:  the input used for the current entity, needed for boundary checks
6234  *
6235  * parse the declaration for a Mixed Element content
6236  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6237  *
6238  * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6239  *
6240  * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6241  *
6242  * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6243  *
6244  * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6245  *
6246  * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6247  * TODO Parameter-entity replacement text must be properly nested
6248  *      with parenthesized groups. That is to say, if either of the
6249  *      opening or closing parentheses in a choice, seq, or Mixed
6250  *      construct is contained in the replacement text for a parameter
6251  *      entity, both must be contained in the same replacement text. For
6252  *      interoperability, if a parameter-entity reference appears in a
6253  *      choice, seq, or Mixed construct, its replacement text should not
6254  *      be empty, and neither the first nor last non-blank character of
6255  *      the replacement text should be a connector (| or ,).
6256  *
6257  * Returns the tree of xmlElementContentPtr describing the element
6258  *          hierarchy.
6259  */
6260 xmlElementContentPtr
6261 xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6262     /* stub left for API/ABI compat */
6263     return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6264 }
6265
6266 /**
6267  * xmlParseElementContentDecl:
6268  * @ctxt:  an XML parser context
6269  * @name:  the name of the element being defined.
6270  * @result:  the Element Content pointer will be stored here if any
6271  *
6272  * parse the declaration for an Element content either Mixed or Children,
6273  * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6274  * 
6275  * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6276  *
6277  * returns: the type of element content XML_ELEMENT_TYPE_xxx
6278  */
6279
6280 int
6281 xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6282                            xmlElementContentPtr *result) {
6283
6284     xmlElementContentPtr tree = NULL;
6285     int inputid = ctxt->input->id;
6286     int res;
6287
6288     *result = NULL;
6289
6290     if (RAW != '(') {
6291         xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6292                 "xmlParseElementContentDecl : %s '(' expected\n", name);
6293         return(-1);
6294     }
6295     NEXT;
6296     GROW;
6297     SKIP_BLANKS;
6298     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6299         tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6300         res = XML_ELEMENT_TYPE_MIXED;
6301     } else {
6302         tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6303         res = XML_ELEMENT_TYPE_ELEMENT;
6304     }
6305     SKIP_BLANKS;
6306     *result = tree;
6307     return(res);
6308 }
6309
6310 /**
6311  * xmlParseElementDecl:
6312  * @ctxt:  an XML parser context
6313  *
6314  * parse an Element declaration.
6315  *
6316  * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6317  *
6318  * [ VC: Unique Element Type Declaration ]
6319  * No element type may be declared more than once
6320  *
6321  * Returns the type of the element, or -1 in case of error
6322  */
6323 int
6324 xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6325     const xmlChar *name;
6326     int ret = -1;
6327     xmlElementContentPtr content  = NULL;
6328
6329     /* GROW; done in the caller */
6330     if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6331         xmlParserInputPtr input = ctxt->input;
6332
6333         SKIP(9);
6334         if (!IS_BLANK_CH(CUR)) {
6335             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6336                            "Space required after 'ELEMENT'\n");
6337         }
6338         SKIP_BLANKS;
6339         name = xmlParseName(ctxt);
6340         if (name == NULL) {
6341             xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6342                            "xmlParseElementDecl: no name for Element\n");
6343             return(-1);
6344         }
6345         while ((RAW == 0) && (ctxt->inputNr > 1))
6346             xmlPopInput(ctxt);
6347         if (!IS_BLANK_CH(CUR)) {
6348             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6349                            "Space required after the element name\n");
6350         }
6351         SKIP_BLANKS;
6352         if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6353             SKIP(5);
6354             /*
6355              * Element must always be empty.
6356              */
6357             ret = XML_ELEMENT_TYPE_EMPTY;
6358         } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6359                    (NXT(2) == 'Y')) {
6360             SKIP(3);
6361             /*
6362              * Element is a generic container.
6363              */
6364             ret = XML_ELEMENT_TYPE_ANY;
6365         } else if (RAW == '(') {
6366             ret = xmlParseElementContentDecl(ctxt, name, &content);
6367         } else {
6368             /*
6369              * [ WFC: PEs in Internal Subset ] error handling.
6370              */
6371             if ((RAW == '%') && (ctxt->external == 0) &&
6372                 (ctxt->inputNr == 1)) {
6373                 xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6374           "PEReference: forbidden within markup decl in internal subset\n");
6375             } else {
6376                 xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6377                       "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6378             }
6379             return(-1);
6380         }
6381
6382         SKIP_BLANKS;
6383         /*
6384          * Pop-up of finished entities.
6385          */
6386         while ((RAW == 0) && (ctxt->inputNr > 1))
6387             xmlPopInput(ctxt);
6388         SKIP_BLANKS;
6389
6390         if (RAW != '>') {
6391             xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6392             if (content != NULL) {
6393                 xmlFreeDocElementContent(ctxt->myDoc, content);
6394             }
6395         } else {
6396             if (input != ctxt->input) {
6397                 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6398     "Element declaration doesn't start and stop in the same entity\n");
6399             }
6400                 
6401             NEXT;
6402             if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6403                 (ctxt->sax->elementDecl != NULL)) {
6404                 if (content != NULL)
6405                     content->parent = NULL;
6406                 ctxt->sax->elementDecl(ctxt->userData, name, ret,
6407                                        content);
6408                 if ((content != NULL) && (content->parent == NULL)) {
6409                     /*
6410                      * this is a trick: if xmlAddElementDecl is called,
6411                      * instead of copying the full tree it is plugged directly
6412                      * if called from the parser. Avoid duplicating the 
6413                      * interfaces or change the API/ABI
6414                      */
6415                     xmlFreeDocElementContent(ctxt->myDoc, content);
6416                 }
6417             } else if (content != NULL) {
6418                 xmlFreeDocElementContent(ctxt->myDoc, content);
6419             }
6420         }
6421     }
6422     return(ret);
6423 }
6424
6425 /**
6426  * xmlParseConditionalSections
6427  * @ctxt:  an XML parser context
6428  *
6429  * [61] conditionalSect ::= includeSect | ignoreSect 
6430  * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 
6431  * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6432  * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6433  * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6434  */
6435
6436 static void
6437 xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6438     int id = ctxt->input->id;
6439
6440     SKIP(3);
6441     SKIP_BLANKS;
6442     if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6443         SKIP(7);
6444         SKIP_BLANKS;
6445         if (RAW != '[') {
6446             xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6447         } else {
6448             if (ctxt->input->id != id) {
6449                 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6450             "All markup of the conditional section is not in the same entity\n",
6451                                      NULL, NULL);
6452             }
6453             NEXT;
6454         }
6455         if (xmlParserDebugEntities) {
6456             if ((ctxt->input != NULL) && (ctxt->input->filename))
6457                 xmlGenericError(xmlGenericErrorContext,
6458                         "%s(%d): ", ctxt->input->filename,
6459                         ctxt->input->line);
6460             xmlGenericError(xmlGenericErrorContext,
6461                     "Entering INCLUDE Conditional Section\n");
6462         }
6463
6464         while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
6465                (NXT(2) != '>'))) {
6466             const xmlChar *check = CUR_PTR;
6467             unsigned int cons = ctxt->input->consumed;
6468
6469             if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6470                 xmlParseConditionalSections(ctxt);
6471             } else if (IS_BLANK_CH(CUR)) {
6472                 NEXT;
6473             } else if (RAW == '%') {
6474                 xmlParsePEReference(ctxt);
6475             } else
6476                 xmlParseMarkupDecl(ctxt);
6477
6478             /*
6479              * Pop-up of finished entities.
6480              */
6481             while ((RAW == 0) && (ctxt->inputNr > 1))
6482                 xmlPopInput(ctxt);
6483
6484             if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
6485                 xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6486                 break;
6487             }
6488         }
6489         if (xmlParserDebugEntities) {
6490             if ((ctxt->input != NULL) && (ctxt->input->filename))
6491                 xmlGenericError(xmlGenericErrorContext,
6492                         "%s(%d): ", ctxt->input->filename,
6493                         ctxt->input->line);
6494             xmlGenericError(xmlGenericErrorContext,
6495                     "Leaving INCLUDE Conditional Section\n");
6496         }
6497
6498     } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6499         int state;
6500         xmlParserInputState instate;
6501         int depth = 0;
6502
6503         SKIP(6);
6504         SKIP_BLANKS;
6505         if (RAW != '[') {
6506             xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6507         } else {
6508             if (ctxt->input->id != id) {
6509                 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6510             "All markup of the conditional section is not in the same entity\n",
6511                                      NULL, NULL);
6512             }
6513             NEXT;
6514         }
6515         if (xmlParserDebugEntities) {
6516             if ((ctxt->input != NULL) && (ctxt->input->filename))
6517                 xmlGenericError(xmlGenericErrorContext,
6518                         "%s(%d): ", ctxt->input->filename,
6519                         ctxt->input->line);
6520             xmlGenericError(xmlGenericErrorContext,
6521                     "Entering IGNORE Conditional Section\n");
6522         }
6523
6524         /*
6525          * Parse up to the end of the conditional section
6526          * But disable SAX event generating DTD building in the meantime
6527          */
6528         state = ctxt->disableSAX;
6529         instate = ctxt->instate;
6530         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
6531         ctxt->instate = XML_PARSER_IGNORE;
6532
6533         while ((depth >= 0) && (RAW != 0)) {
6534           if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6535             depth++;
6536             SKIP(3);
6537             continue;
6538           }
6539           if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6540             if (--depth >= 0) SKIP(3);
6541             continue;
6542           }
6543           NEXT;
6544           continue;
6545         }
6546
6547         ctxt->disableSAX = state;
6548         ctxt->instate = instate;
6549
6550         if (xmlParserDebugEntities) {
6551             if ((ctxt->input != NULL) && (ctxt->input->filename))
6552                 xmlGenericError(xmlGenericErrorContext,
6553                         "%s(%d): ", ctxt->input->filename,
6554                         ctxt->input->line);
6555             xmlGenericError(xmlGenericErrorContext,
6556                     "Leaving IGNORE Conditional Section\n");
6557         }
6558
6559     } else {
6560         xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6561     }
6562
6563     if (RAW == 0)
6564         SHRINK;
6565
6566     if (RAW == 0) {
6567         xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6568     } else {
6569         if (ctxt->input->id != id) {
6570             xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6571         "All markup of the conditional section is not in the same entity\n",
6572                                  NULL, NULL);
6573         }
6574         SKIP(3);
6575     }
6576 }
6577
6578 /**
6579  * xmlParseMarkupDecl:
6580  * @ctxt:  an XML parser context
6581  * 
6582  * parse Markup declarations
6583  *
6584  * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6585  *                     NotationDecl | PI | Comment
6586  *
6587  * [ VC: Proper Declaration/PE Nesting ]
6588  * Parameter-entity replacement text must be properly nested with
6589  * markup declarations. That is to say, if either the first character
6590  * or the last character of a markup declaration (markupdecl above) is
6591  * contained in the replacement text for a parameter-entity reference,
6592  * both must be contained in the same replacement text.
6593  *
6594  * [ WFC: PEs in Internal Subset ]
6595  * In the internal DTD subset, parameter-entity references can occur
6596  * only where markup declarations can occur, not within markup declarations.
6597  * (This does not apply to references that occur in external parameter
6598  * entities or to the external subset.) 
6599  */
6600 void
6601 xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6602     GROW;
6603     if (CUR == '<') {
6604         if (NXT(1) == '!') {
6605             switch (NXT(2)) {
6606                 case 'E':
6607                     if (NXT(3) == 'L')
6608                         xmlParseElementDecl(ctxt);
6609                     else if (NXT(3) == 'N')
6610                         xmlParseEntityDecl(ctxt);
6611                     break;
6612                 case 'A':
6613                     xmlParseAttributeListDecl(ctxt);
6614                     break;
6615                 case 'N':
6616                     xmlParseNotationDecl(ctxt);
6617                     break;
6618                 case '-':
6619                     xmlParseComment(ctxt);
6620                     break;
6621                 default:
6622                     /* there is an error but it will be detected later */
6623                     break;
6624             }
6625         } else if (NXT(1) == '?') {
6626             xmlParsePI(ctxt);
6627         }
6628     }
6629     /*
6630      * This is only for internal subset. On external entities,
6631      * the replacement is done before parsing stage
6632      */
6633     if ((ctxt->external == 0) && (ctxt->inputNr == 1))
6634         xmlParsePEReference(ctxt);
6635
6636     /*
6637      * Conditional sections are allowed from entities included
6638      * by PE References in the internal subset.
6639      */
6640     if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
6641         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6642             xmlParseConditionalSections(ctxt);
6643         }
6644     }
6645
6646     ctxt->instate = XML_PARSER_DTD;
6647 }
6648
6649 /**
6650  * xmlParseTextDecl:
6651  * @ctxt:  an XML parser context
6652  *
6653  * parse an XML declaration header for external entities
6654  *
6655  * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
6656  */
6657
6658 void
6659 xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
6660     xmlChar *version;
6661     const xmlChar *encoding;
6662
6663     /*
6664      * We know that '<?xml' is here.
6665      */
6666     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
6667         SKIP(5);
6668     } else {
6669         xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
6670         return;
6671     }
6672
6673     if (!IS_BLANK_CH(CUR)) {
6674         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6675                        "Space needed after '<?xml'\n");
6676     }
6677     SKIP_BLANKS;
6678
6679     /*
6680      * We may have the VersionInfo here.
6681      */
6682     version = xmlParseVersionInfo(ctxt);
6683     if (version == NULL)
6684         version = xmlCharStrdup(XML_DEFAULT_VERSION);
6685     else {
6686         if (!IS_BLANK_CH(CUR)) {
6687             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6688                            "Space needed here\n");
6689         }
6690     }
6691     ctxt->input->version = version;
6692
6693     /*
6694      * We must have the encoding declaration
6695      */
6696     encoding = xmlParseEncodingDecl(ctxt);
6697     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
6698         /*
6699          * The XML REC instructs us to stop parsing right here
6700          */
6701         return;
6702     }
6703     if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
6704         xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
6705                        "Missing encoding in text declaration\n");
6706     }
6707
6708     SKIP_BLANKS;
6709     if ((RAW == '?') && (NXT(1) == '>')) {
6710         SKIP(2);
6711     } else if (RAW == '>') {
6712         /* Deprecated old WD ... */
6713         xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
6714         NEXT;
6715     } else {
6716         xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
6717         MOVETO_ENDTAG(CUR_PTR);
6718         NEXT;
6719     }
6720 }
6721
6722 /**
6723  * xmlParseExternalSubset:
6724  * @ctxt:  an XML parser context
6725  * @ExternalID: the external identifier
6726  * @SystemID: the system identifier (or URL)
6727  * 
6728  * parse Markup declarations from an external subset
6729  *
6730  * [30] extSubset ::= textDecl? extSubsetDecl
6731  *
6732  * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
6733  */
6734 void
6735 xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
6736                        const xmlChar *SystemID) {
6737     xmlDetectSAX2(ctxt);
6738     GROW;
6739
6740     if ((ctxt->encoding == NULL) &&
6741         (ctxt->input->end - ctxt->input->cur >= 4)) {
6742         xmlChar start[4];
6743         xmlCharEncoding enc;
6744
6745         start[0] = RAW;
6746         start[1] = NXT(1);
6747         start[2] = NXT(2);
6748         start[3] = NXT(3);
6749         enc = xmlDetectCharEncoding(start, 4);
6750         if (enc != XML_CHAR_ENCODING_NONE)
6751             xmlSwitchEncoding(ctxt, enc);
6752     }
6753
6754     if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
6755         xmlParseTextDecl(ctxt);
6756         if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
6757             /*
6758              * The XML REC instructs us to stop parsing right here
6759              */
6760             ctxt->instate = XML_PARSER_EOF;
6761             return;
6762         }
6763     }
6764     if (ctxt->myDoc == NULL) {
6765         ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
6766         if (ctxt->myDoc == NULL) {
6767             xmlErrMemory(ctxt, "New Doc failed");
6768             return;
6769         }
6770         ctxt->myDoc->properties = XML_DOC_INTERNAL;
6771     }
6772     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
6773         xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
6774
6775     ctxt->instate = XML_PARSER_DTD;
6776     ctxt->external = 1;
6777     while (((RAW == '<') && (NXT(1) == '?')) ||
6778            ((RAW == '<') && (NXT(1) == '!')) ||
6779            (RAW == '%') || IS_BLANK_CH(CUR)) {
6780         const xmlChar *check = CUR_PTR;
6781         unsigned int cons = ctxt->input->consumed;
6782
6783         GROW;
6784         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6785             xmlParseConditionalSections(ctxt);
6786         } else if (IS_BLANK_CH(CUR)) {
6787             NEXT;
6788         } else if (RAW == '%') {
6789             xmlParsePEReference(ctxt);
6790         } else
6791             xmlParseMarkupDecl(ctxt);
6792
6793         /*
6794          * Pop-up of finished entities.
6795          */
6796         while ((RAW == 0) && (ctxt->inputNr > 1))
6797             xmlPopInput(ctxt);
6798
6799         if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
6800             xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6801             break;
6802         }
6803     }
6804     
6805     if (RAW != 0) {
6806         xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6807     }
6808
6809 }
6810
6811 /**
6812  * xmlParseReference:
6813  * @ctxt:  an XML parser context
6814  *
6815  * parse and handle entity references in content, depending on the SAX
6816  * interface, this may end-up in a call to character() if this is a
6817  * CharRef, a predefined entity, if there is no reference() callback.
6818  * or if the parser was asked to switch to that mode.
6819  *
6820  * [67] Reference ::= EntityRef | CharRef
6821  */
6822 void
6823 xmlParseReference(xmlParserCtxtPtr ctxt) {
6824     xmlEntityPtr ent;
6825     xmlChar *val;
6826     int was_checked;
6827     xmlNodePtr list = NULL;
6828     xmlParserErrors ret = XML_ERR_OK;
6829
6830
6831     if (RAW != '&')
6832         return;
6833
6834     /*
6835      * Simple case of a CharRef
6836      */
6837     if (NXT(1) == '#') {
6838         int i = 0;
6839         xmlChar out[10];
6840         int hex = NXT(2);
6841         int value = xmlParseCharRef(ctxt);
6842
6843         if (value == 0)
6844             return;
6845         if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
6846             /*
6847              * So we are using non-UTF-8 buffers
6848              * Check that the char fit on 8bits, if not
6849              * generate a CharRef.
6850              */
6851             if (value <= 0xFF) {
6852                 out[0] = value;
6853                 out[1] = 0;
6854                 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
6855                     (!ctxt->disableSAX))
6856                     ctxt->sax->characters(ctxt->userData, out, 1);
6857             } else {
6858                 if ((hex == 'x') || (hex == 'X'))
6859                     snprintf((char *)out, sizeof(out), "#x%X", value);
6860                 else
6861                     snprintf((char *)out, sizeof(out), "#%d", value);
6862                 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
6863                     (!ctxt->disableSAX))
6864                     ctxt->sax->reference(ctxt->userData, out);
6865             }
6866         } else {
6867             /*
6868              * Just encode the value in UTF-8
6869              */
6870             COPY_BUF(0 ,out, i, value);
6871             out[i] = 0;
6872             if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
6873                 (!ctxt->disableSAX))
6874                 ctxt->sax->characters(ctxt->userData, out, i);
6875         }
6876         return;
6877     }
6878
6879     /*
6880      * We are seeing an entity reference
6881      */
6882     ent = xmlParseEntityRef(ctxt);
6883     if (ent == NULL) return;
6884     if (!ctxt->wellFormed)
6885         return;
6886     was_checked = ent->checked;
6887
6888     /* special case of predefined entities */
6889     if ((ent->name == NULL) ||
6890         (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
6891         val = ent->content;
6892         if (val == NULL) return;
6893         /*
6894          * inline the entity.
6895          */
6896         if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
6897             (!ctxt->disableSAX))
6898             ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
6899         return;
6900     }
6901
6902     /*
6903      * The first reference to the entity trigger a parsing phase
6904      * where the ent->children is filled with the result from
6905      * the parsing.
6906      */
6907     if (ent->checked == 0) {
6908         unsigned long oldnbent = ctxt->nbentities;
6909
6910         /*
6911          * This is a bit hackish but this seems the best
6912          * way to make sure both SAX and DOM entity support
6913          * behaves okay.
6914          */
6915         void *user_data;
6916         if (ctxt->userData == ctxt)
6917             user_data = NULL;
6918         else
6919             user_data = ctxt->userData;
6920
6921         /*
6922          * Check that this entity is well formed
6923          * 4.3.2: An internal general parsed entity is well-formed
6924          * if its replacement text matches the production labeled
6925          * content.
6926          */
6927         if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
6928             ctxt->depth++;
6929             ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
6930                                                       user_data, &list);
6931             ctxt->depth--;
6932
6933         } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
6934             ctxt->depth++;
6935             ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
6936                                            user_data, ctxt->depth, ent->URI,
6937                                            ent->ExternalID, &list);
6938             ctxt->depth--;
6939         } else {
6940             ret = XML_ERR_ENTITY_PE_INTERNAL;
6941             xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
6942                          "invalid entity type found\n", NULL);
6943         }
6944
6945         /*
6946          * Store the number of entities needing parsing for this entity
6947          * content and do checkings
6948          */
6949         ent->checked = ctxt->nbentities - oldnbent;
6950         if (ret == XML_ERR_ENTITY_LOOP) {
6951             xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
6952             xmlFreeNodeList(list);
6953             return;
6954         }
6955         if (xmlParserEntityCheck(ctxt, 0, ent)) {
6956             xmlFreeNodeList(list);
6957             return;
6958         }
6959
6960         if ((ret == XML_ERR_OK) && (list != NULL)) {
6961             if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
6962              (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
6963                 (ent->children == NULL)) {
6964                 ent->children = list;
6965                 if (ctxt->replaceEntities) {
6966                     /*
6967                      * Prune it directly in the generated document
6968                      * except for single text nodes.
6969                      */
6970                     if (((list->type == XML_TEXT_NODE) &&
6971                          (list->next == NULL)) ||
6972                         (ctxt->parseMode == XML_PARSE_READER)) {
6973                         list->parent = (xmlNodePtr) ent;
6974                         list = NULL;
6975                         ent->owner = 1;
6976                     } else {
6977                         ent->owner = 0;
6978                         while (list != NULL) {
6979                             list->parent = (xmlNodePtr) ctxt->node;
6980                             list->doc = ctxt->myDoc;
6981                             if (list->next == NULL)
6982                                 ent->last = list;
6983                             list = list->next;
6984                         }
6985                         list = ent->children;
6986 #ifdef LIBXML_LEGACY_ENABLED
6987                         if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
6988                           xmlAddEntityReference(ent, list, NULL);
6989 #endif /* LIBXML_LEGACY_ENABLED */
6990                     }
6991                 } else {
6992                     ent->owner = 1;
6993                     while (list != NULL) {
6994                         list->parent = (xmlNodePtr) ent;
6995                         if (list->next == NULL)
6996                             ent->last = list;
6997                         list = list->next;
6998                     }
6999                 }
7000             } else {
7001                 xmlFreeNodeList(list);
7002                 list = NULL;
7003             }
7004         } else if ((ret != XML_ERR_OK) &&
7005                    (ret != XML_WAR_UNDECLARED_ENTITY)) {
7006             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7007                      "Entity '%s' failed to parse\n", ent->name);
7008         } else if (list != NULL) {
7009             xmlFreeNodeList(list);
7010             list = NULL;
7011         }
7012         if (ent->checked == 0)
7013             ent->checked = 1;
7014     } else if (ent->checked != 1) {
7015         ctxt->nbentities += ent->checked;
7016     }
7017
7018     /*
7019      * Now that the entity content has been gathered
7020      * provide it to the application, this can take different forms based
7021      * on the parsing modes.
7022      */
7023     if (ent->children == NULL) {
7024         /*
7025          * Probably running in SAX mode and the callbacks don't
7026          * build the entity content. So unless we already went
7027          * though parsing for first checking go though the entity
7028          * content to generate callbacks associated to the entity
7029          */
7030         if (was_checked != 0) {
7031             void *user_data;
7032             /*
7033              * This is a bit hackish but this seems the best
7034              * way to make sure both SAX and DOM entity support
7035              * behaves okay.
7036              */
7037             if (ctxt->userData == ctxt)
7038                 user_data = NULL;
7039             else
7040                 user_data = ctxt->userData;
7041
7042             if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7043                 ctxt->depth++;
7044                 ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7045                                    ent->content, user_data, NULL);
7046                 ctxt->depth--;
7047             } else if (ent->etype ==
7048                        XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7049                 ctxt->depth++;
7050                 ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7051                            ctxt->sax, user_data, ctxt->depth,
7052                            ent->URI, ent->ExternalID, NULL);
7053                 ctxt->depth--;
7054             } else {
7055                 ret = XML_ERR_ENTITY_PE_INTERNAL;
7056                 xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7057                              "invalid entity type found\n", NULL);
7058             }
7059             if (ret == XML_ERR_ENTITY_LOOP) {
7060                 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7061                 return;
7062             }
7063         }
7064         if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7065             (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7066             /*
7067              * Entity reference callback comes second, it's somewhat
7068              * superfluous but a compatibility to historical behaviour
7069              */
7070             ctxt->sax->reference(ctxt->userData, ent->name);
7071         }
7072         return;
7073     }
7074
7075     /*
7076      * If we didn't get any children for the entity being built
7077      */
7078     if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7079         (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7080         /*
7081          * Create a node.
7082          */
7083         ctxt->sax->reference(ctxt->userData, ent->name);
7084         return;
7085     }
7086
7087     if ((ctxt->replaceEntities) || (ent->children == NULL))  {
7088         /*
7089          * There is a problem on the handling of _private for entities
7090          * (bug 155816): Should we copy the content of the field from
7091          * the entity (possibly overwriting some value set by the user
7092          * when a copy is created), should we leave it alone, or should
7093          * we try to take care of different situations?  The problem
7094          * is exacerbated by the usage of this field by the xmlReader.
7095          * To fix this bug, we look at _private on the created node
7096          * and, if it's NULL, we copy in whatever was in the entity.
7097          * If it's not NULL we leave it alone.  This is somewhat of a
7098          * hack - maybe we should have further tests to determine
7099          * what to do.
7100          */
7101         if ((ctxt->node != NULL) && (ent->children != NULL)) {
7102             /*
7103              * Seems we are generating the DOM content, do
7104              * a simple tree copy for all references except the first
7105              * In the first occurrence list contains the replacement.
7106              * progressive == 2 means we are operating on the Reader
7107              * and since nodes are discarded we must copy all the time.
7108              */
7109             if (((list == NULL) && (ent->owner == 0)) ||
7110                 (ctxt->parseMode == XML_PARSE_READER)) {
7111                 xmlNodePtr nw = NULL, cur, firstChild = NULL;
7112
7113                 /*
7114                  * when operating on a reader, the entities definitions
7115                  * are always owning the entities subtree.
7116                 if (ctxt->parseMode == XML_PARSE_READER)
7117                     ent->owner = 1;
7118                  */
7119
7120                 cur = ent->children;
7121                 while (cur != NULL) {
7122                     nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7123                     if (nw != NULL) {
7124                         if (nw->_private == NULL)
7125                             nw->_private = cur->_private;
7126                         if (firstChild == NULL){
7127                             firstChild = nw;
7128                         }
7129                         nw = xmlAddChild(ctxt->node, nw);
7130                     }
7131                     if (cur == ent->last) {
7132                         /*
7133                          * needed to detect some strange empty
7134                          * node cases in the reader tests
7135                          */
7136                         if ((ctxt->parseMode == XML_PARSE_READER) &&
7137                             (nw != NULL) &&
7138                             (nw->type == XML_ELEMENT_NODE) &&
7139                             (nw->children == NULL))
7140                             nw->extra = 1;
7141
7142                         break;
7143                     }
7144                     cur = cur->next;
7145                 }
7146 #ifdef LIBXML_LEGACY_ENABLED
7147                 if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7148                   xmlAddEntityReference(ent, firstChild, nw);
7149 #endif /* LIBXML_LEGACY_ENABLED */
7150             } else if (list == NULL) {
7151                 xmlNodePtr nw = NULL, cur, next, last,
7152                            firstChild = NULL;
7153                 /*
7154                  * Copy the entity child list and make it the new
7155                  * entity child list. The goal is to make sure any
7156                  * ID or REF referenced will be the one from the
7157                  * document content and not the entity copy.
7158                  */
7159                 cur = ent->children;
7160                 ent->children = NULL;
7161                 last = ent->last;
7162                 ent->last = NULL;
7163                 while (cur != NULL) {
7164                     next = cur->next;
7165                     cur->next = NULL;
7166                     cur->parent = NULL;
7167                     nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7168                     if (nw != NULL) {
7169                         if (nw->_private == NULL)
7170                             nw->_private = cur->_private;
7171                         if (firstChild == NULL){
7172                             firstChild = cur;
7173                         }
7174                         xmlAddChild((xmlNodePtr) ent, nw);
7175                         xmlAddChild(ctxt->node, cur);
7176                     }
7177                     if (cur == last)
7178                         break;
7179                     cur = next;
7180                 }
7181                 if (ent->owner == 0)
7182                     ent->owner = 1;
7183 #ifdef LIBXML_LEGACY_ENABLED
7184                 if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7185                   xmlAddEntityReference(ent, firstChild, nw);
7186 #endif /* LIBXML_LEGACY_ENABLED */
7187             } else {
7188                 const xmlChar *nbktext;
7189
7190                 /*
7191                  * the name change is to avoid coalescing of the
7192                  * node with a possible previous text one which
7193                  * would make ent->children a dangling pointer
7194                  */
7195                 nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7196                                         -1);
7197                 if (ent->children->type == XML_TEXT_NODE)
7198                     ent->children->name = nbktext;
7199                 if ((ent->last != ent->children) &&
7200                     (ent->last->type == XML_TEXT_NODE))
7201                     ent->last->name = nbktext;
7202                 xmlAddChildList(ctxt->node, ent->children);
7203             }
7204
7205             /*
7206              * This is to avoid a nasty side effect, see
7207              * characters() in SAX.c
7208              */
7209             ctxt->nodemem = 0;
7210             ctxt->nodelen = 0;
7211             return;
7212         }
7213     }
7214 }
7215
7216 /**
7217  * xmlParseEntityRef:
7218  * @ctxt:  an XML parser context
7219  *
7220  * parse ENTITY references declarations
7221  *
7222  * [68] EntityRef ::= '&' Name ';'
7223  *
7224  * [ WFC: Entity Declared ]
7225  * In a document without any DTD, a document with only an internal DTD
7226  * subset which contains no parameter entity references, or a document
7227  * with "standalone='yes'", the Name given in the entity reference
7228  * must match that in an entity declaration, except that well-formed
7229  * documents need not declare any of the following entities: amp, lt,
7230  * gt, apos, quot.  The declaration of a parameter entity must precede
7231  * any reference to it.  Similarly, the declaration of a general entity
7232  * must precede any reference to it which appears in a default value in an
7233  * attribute-list declaration. Note that if entities are declared in the
7234  * external subset or in external parameter entities, a non-validating
7235  * processor is not obligated to read and process their declarations;
7236  * for such documents, the rule that an entity must be declared is a
7237  * well-formedness constraint only if standalone='yes'.
7238  *
7239  * [ WFC: Parsed Entity ]
7240  * An entity reference must not contain the name of an unparsed entity
7241  *
7242  * Returns the xmlEntityPtr if found, or NULL otherwise.
7243  */
7244 xmlEntityPtr
7245 xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7246     const xmlChar *name;
7247     xmlEntityPtr ent = NULL;
7248
7249     GROW;
7250
7251     if (RAW != '&')
7252         return(NULL);
7253     NEXT;
7254     name = xmlParseName(ctxt);
7255     if (name == NULL) {
7256         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7257                        "xmlParseEntityRef: no name\n");
7258         return(NULL);
7259     }
7260     if (RAW != ';') {
7261         xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7262         return(NULL);
7263     }
7264     NEXT;
7265
7266     /*
7267      * Predefined entites override any extra definition
7268      */
7269     if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7270         ent = xmlGetPredefinedEntity(name);
7271         if (ent != NULL)
7272             return(ent);
7273     }
7274
7275     /*
7276      * Increate the number of entity references parsed
7277      */
7278     ctxt->nbentities++;
7279
7280     /*
7281      * Ask first SAX for entity resolution, otherwise try the
7282      * entities which may have stored in the parser context.
7283      */
7284     if (ctxt->sax != NULL) {
7285         if (ctxt->sax->getEntity != NULL)
7286             ent = ctxt->sax->getEntity(ctxt->userData, name);
7287         if ((ctxt->wellFormed == 1 ) && (ent == NULL) && 
7288             (ctxt->options & XML_PARSE_OLDSAX))
7289             ent = xmlGetPredefinedEntity(name);
7290         if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7291             (ctxt->userData==ctxt)) {
7292             ent = xmlSAX2GetEntity(ctxt, name);
7293         }
7294     }
7295     /*
7296      * [ WFC: Entity Declared ]
7297      * In a document without any DTD, a document with only an
7298      * internal DTD subset which contains no parameter entity
7299      * references, or a document with "standalone='yes'", the
7300      * Name given in the entity reference must match that in an
7301      * entity declaration, except that well-formed documents
7302      * need not declare any of the following entities: amp, lt,
7303      * gt, apos, quot.
7304      * The declaration of a parameter entity must precede any
7305      * reference to it.
7306      * Similarly, the declaration of a general entity must
7307      * precede any reference to it which appears in a default
7308      * value in an attribute-list declaration. Note that if
7309      * entities are declared in the external subset or in
7310      * external parameter entities, a non-validating processor
7311      * is not obligated to read and process their declarations;
7312      * for such documents, the rule that an entity must be
7313      * declared is a well-formedness constraint only if
7314      * standalone='yes'.
7315      */
7316     if (ent == NULL) {
7317         if ((ctxt->standalone == 1) ||
7318             ((ctxt->hasExternalSubset == 0) &&
7319              (ctxt->hasPErefs == 0))) {
7320             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7321                      "Entity '%s' not defined\n", name);
7322         } else {
7323             xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7324                      "Entity '%s' not defined\n", name);
7325             if ((ctxt->inSubset == 0) &&
7326                 (ctxt->sax != NULL) &&
7327                 (ctxt->sax->reference != NULL)) {
7328                 ctxt->sax->reference(ctxt->userData, name);
7329             }
7330         }
7331         ctxt->valid = 0;
7332     }
7333
7334     /*
7335      * [ WFC: Parsed Entity ]
7336      * An entity reference must not contain the name of an
7337      * unparsed entity
7338      */
7339     else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7340         xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7341                  "Entity reference to unparsed entity %s\n", name);
7342     }
7343
7344     /*
7345      * [ WFC: No External Entity References ]
7346      * Attribute values cannot contain direct or indirect
7347      * entity references to external entities.
7348      */
7349     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7350              (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7351         xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7352              "Attribute references external entity '%s'\n", name);
7353     }
7354     /*
7355      * [ WFC: No < in Attribute Values ]
7356      * The replacement text of any entity referred to directly or
7357      * indirectly in an attribute value (other than "&lt;") must
7358      * not contain a <. 
7359      */
7360     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7361              (ent != NULL) && (ent->content != NULL) &&
7362              (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7363              (xmlStrchr(ent->content, '<'))) {
7364         xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7365     "'<' in entity '%s' is not allowed in attributes values\n", name);
7366     }
7367
7368     /*
7369      * Internal check, no parameter entities here ...
7370      */
7371     else {
7372         switch (ent->etype) {
7373             case XML_INTERNAL_PARAMETER_ENTITY:
7374             case XML_EXTERNAL_PARAMETER_ENTITY:
7375             xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7376              "Attempt to reference the parameter entity '%s'\n",
7377                               name);
7378             break;
7379             default:
7380             break;
7381         }
7382     }
7383
7384     /*
7385      * [ WFC: No Recursion ]
7386      * A parsed entity must not contain a recursive reference
7387      * to itself, either directly or indirectly. 
7388      * Done somewhere else
7389      */
7390     return(ent);
7391 }
7392
7393 /**
7394  * xmlParseStringEntityRef:
7395  * @ctxt:  an XML parser context
7396  * @str:  a pointer to an index in the string
7397  *
7398  * parse ENTITY references declarations, but this version parses it from
7399  * a string value.
7400  *
7401  * [68] EntityRef ::= '&' Name ';'
7402  *
7403  * [ WFC: Entity Declared ]
7404  * In a document without any DTD, a document with only an internal DTD
7405  * subset which contains no parameter entity references, or a document
7406  * with "standalone='yes'", the Name given in the entity reference
7407  * must match that in an entity declaration, except that well-formed
7408  * documents need not declare any of the following entities: amp, lt,
7409  * gt, apos, quot.  The declaration of a parameter entity must precede
7410  * any reference to it.  Similarly, the declaration of a general entity
7411  * must precede any reference to it which appears in a default value in an
7412  * attribute-list declaration. Note that if entities are declared in the
7413  * external subset or in external parameter entities, a non-validating
7414  * processor is not obligated to read and process their declarations;
7415  * for such documents, the rule that an entity must be declared is a
7416  * well-formedness constraint only if standalone='yes'.
7417  *
7418  * [ WFC: Parsed Entity ]
7419  * An entity reference must not contain the name of an unparsed entity
7420  *
7421  * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7422  * is updated to the current location in the string.
7423  */
7424 static xmlEntityPtr
7425 xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7426     xmlChar *name;
7427     const xmlChar *ptr;
7428     xmlChar cur;
7429     xmlEntityPtr ent = NULL;
7430
7431     if ((str == NULL) || (*str == NULL))
7432         return(NULL);
7433     ptr = *str;
7434     cur = *ptr;
7435     if (cur != '&')
7436         return(NULL);
7437
7438     ptr++;
7439     name = xmlParseStringName(ctxt, &ptr);
7440     if (name == NULL) {
7441         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7442                        "xmlParseStringEntityRef: no name\n");
7443         *str = ptr;
7444         return(NULL);
7445     }
7446     if (*ptr != ';') {
7447         xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7448         xmlFree(name);
7449         *str = ptr;
7450         return(NULL);
7451     }
7452     ptr++;
7453
7454
7455     /*
7456      * Predefined entites override any extra definition
7457      */
7458     if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7459         ent = xmlGetPredefinedEntity(name);
7460         if (ent != NULL) {
7461             xmlFree(name);
7462             *str = ptr;
7463             return(ent);
7464         }
7465     }
7466
7467     /*
7468      * Increate the number of entity references parsed
7469      */
7470     ctxt->nbentities++;
7471
7472     /*
7473      * Ask first SAX for entity resolution, otherwise try the
7474      * entities which may have stored in the parser context.
7475      */
7476     if (ctxt->sax != NULL) {
7477         if (ctxt->sax->getEntity != NULL)
7478             ent = ctxt->sax->getEntity(ctxt->userData, name);
7479         if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7480             ent = xmlGetPredefinedEntity(name);
7481         if ((ent == NULL) && (ctxt->userData==ctxt)) {
7482             ent = xmlSAX2GetEntity(ctxt, name);
7483         }
7484     }
7485
7486     /*
7487      * [ WFC: Entity Declared ]
7488      * In a document without any DTD, a document with only an
7489      * internal DTD subset which contains no parameter entity
7490      * references, or a document with "standalone='yes'", the
7491      * Name given in the entity reference must match that in an
7492      * entity declaration, except that well-formed documents
7493      * need not declare any of the following entities: amp, lt,
7494      * gt, apos, quot.
7495      * The declaration of a parameter entity must precede any
7496      * reference to it.
7497      * Similarly, the declaration of a general entity must
7498      * precede any reference to it which appears in a default
7499      * value in an attribute-list declaration. Note that if
7500      * entities are declared in the external subset or in
7501      * external parameter entities, a non-validating processor
7502      * is not obligated to read and process their declarations;
7503      * for such documents, the rule that an entity must be
7504      * declared is a well-formedness constraint only if
7505      * standalone='yes'. 
7506      */
7507     if (ent == NULL) {
7508         if ((ctxt->standalone == 1) ||
7509             ((ctxt->hasExternalSubset == 0) &&
7510              (ctxt->hasPErefs == 0))) {
7511             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7512                      "Entity '%s' not defined\n", name);
7513         } else {
7514             xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7515                           "Entity '%s' not defined\n",
7516                           name);
7517         }
7518         /* TODO ? check regressions ctxt->valid = 0; */
7519     }
7520
7521     /*
7522      * [ WFC: Parsed Entity ]
7523      * An entity reference must not contain the name of an
7524      * unparsed entity
7525      */
7526     else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7527         xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7528                  "Entity reference to unparsed entity %s\n", name);
7529     }
7530
7531     /*
7532      * [ WFC: No External Entity References ]
7533      * Attribute values cannot contain direct or indirect
7534      * entity references to external entities.
7535      */
7536     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7537              (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7538         xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7539          "Attribute references external entity '%s'\n", name);
7540     }
7541     /*
7542      * [ WFC: No < in Attribute Values ]
7543      * The replacement text of any entity referred to directly or
7544      * indirectly in an attribute value (other than "&lt;") must
7545      * not contain a <.
7546      */
7547     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7548              (ent != NULL) && (ent->content != NULL) &&
7549              (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7550              (xmlStrchr(ent->content, '<'))) {
7551         xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7552      "'<' in entity '%s' is not allowed in attributes values\n",
7553                           name);
7554     }
7555
7556     /*
7557      * Internal check, no parameter entities here ...
7558      */
7559     else {
7560         switch (ent->etype) {
7561             case XML_INTERNAL_PARAMETER_ENTITY:
7562             case XML_EXTERNAL_PARAMETER_ENTITY:
7563                 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7564              "Attempt to reference the parameter entity '%s'\n",
7565                                   name);
7566             break;
7567             default:
7568             break;
7569         }
7570     }
7571
7572     /*
7573      * [ WFC: No Recursion ]
7574      * A parsed entity must not contain a recursive reference
7575      * to itself, either directly or indirectly.
7576      * Done somewhere else
7577      */
7578
7579     xmlFree(name);
7580     *str = ptr;
7581     return(ent);
7582 }
7583
7584 /**
7585  * xmlParsePEReference:
7586  * @ctxt:  an XML parser context
7587  *
7588  * parse PEReference declarations
7589  * The entity content is handled directly by pushing it's content as
7590  * a new input stream.
7591  *
7592  * [69] PEReference ::= '%' Name ';'
7593  *
7594  * [ WFC: No Recursion ]
7595  * A parsed entity must not contain a recursive
7596  * reference to itself, either directly or indirectly. 
7597  *
7598  * [ WFC: Entity Declared ]
7599  * In a document without any DTD, a document with only an internal DTD
7600  * subset which contains no parameter entity references, or a document
7601  * with "standalone='yes'", ...  ... The declaration of a parameter
7602  * entity must precede any reference to it...
7603  *
7604  * [ VC: Entity Declared ]
7605  * In a document with an external subset or external parameter entities
7606  * with "standalone='no'", ...  ... The declaration of a parameter entity
7607  * must precede any reference to it...
7608  *
7609  * [ WFC: In DTD ]
7610  * Parameter-entity references may only appear in the DTD.
7611  * NOTE: misleading but this is handled.
7612  */
7613 void
7614 xmlParsePEReference(xmlParserCtxtPtr ctxt)
7615 {
7616     const xmlChar *name;
7617     xmlEntityPtr entity = NULL;
7618     xmlParserInputPtr input;
7619
7620     if (RAW != '%')
7621         return;
7622     NEXT;
7623     name = xmlParseName(ctxt);
7624     if (name == NULL) {
7625         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7626                        "xmlParsePEReference: no name\n");
7627         return;
7628     }
7629     if (RAW != ';') {
7630         xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7631         return;
7632     }
7633
7634     NEXT;
7635
7636     /*
7637      * Increate the number of entity references parsed
7638      */
7639     ctxt->nbentities++;
7640
7641     /*
7642      * Request the entity from SAX
7643      */
7644     if ((ctxt->sax != NULL) &&
7645         (ctxt->sax->getParameterEntity != NULL))
7646         entity = ctxt->sax->getParameterEntity(ctxt->userData,
7647                                                name);
7648     if (entity == NULL) {
7649         /*
7650          * [ WFC: Entity Declared ]
7651          * In a document without any DTD, a document with only an
7652          * internal DTD subset which contains no parameter entity
7653          * references, or a document with "standalone='yes'", ...
7654          * ... The declaration of a parameter entity must precede
7655          * any reference to it...
7656          */
7657         if ((ctxt->standalone == 1) ||
7658             ((ctxt->hasExternalSubset == 0) &&
7659              (ctxt->hasPErefs == 0))) {
7660             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7661                               "PEReference: %%%s; not found\n",
7662                               name);
7663         } else {
7664             /*
7665              * [ VC: Entity Declared ]
7666              * In a document with an external subset or external
7667              * parameter entities with "standalone='no'", ...
7668              * ... The declaration of a parameter entity must
7669              * precede any reference to it...
7670              */
7671             xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7672                           "PEReference: %%%s; not found\n",
7673                           name, NULL);
7674             ctxt->valid = 0;
7675         }
7676     } else {
7677         /*
7678          * Internal checking in case the entity quest barfed
7679          */
7680         if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
7681             (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
7682             xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7683                   "Internal: %%%s; is not a parameter entity\n",
7684                           name, NULL);
7685         } else if (ctxt->input->free != deallocblankswrapper) {
7686             input = xmlNewBlanksWrapperInputStream(ctxt, entity);
7687             if (xmlPushInput(ctxt, input) < 0)
7688                 return;
7689         } else {
7690             /*
7691              * TODO !!!
7692              * handle the extra spaces added before and after
7693              * c.f. http://www.w3.org/TR/REC-xml#as-PE
7694              */
7695             input = xmlNewEntityInputStream(ctxt, entity);
7696             if (xmlPushInput(ctxt, input) < 0)
7697                 return;
7698             if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
7699                 (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
7700                 (IS_BLANK_CH(NXT(5)))) {
7701                 xmlParseTextDecl(ctxt);
7702                 if (ctxt->errNo ==
7703                     XML_ERR_UNSUPPORTED_ENCODING) {
7704                     /*
7705                      * The XML REC instructs us to stop parsing
7706                      * right here
7707                      */
7708                     ctxt->instate = XML_PARSER_EOF;
7709                     return;
7710                 }
7711             }
7712         }
7713     }
7714     ctxt->hasPErefs = 1;
7715 }
7716
7717 /**
7718  * xmlLoadEntityContent:
7719  * @ctxt:  an XML parser context
7720  * @entity: an unloaded system entity
7721  *
7722  * Load the original content of the given system entity from the
7723  * ExternalID/SystemID given. This is to be used for Included in Literal
7724  * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
7725  *
7726  * Returns 0 in case of success and -1 in case of failure
7727  */
7728 static int
7729 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
7730     xmlParserInputPtr input;
7731     xmlBufferPtr buf;
7732     int l, c;
7733     int count = 0;
7734
7735     if ((ctxt == NULL) || (entity == NULL) ||
7736         ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
7737          (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
7738         (entity->content != NULL)) {
7739         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
7740                     "xmlLoadEntityContent parameter error");
7741         return(-1);
7742     }
7743
7744     if (xmlParserDebugEntities)
7745         xmlGenericError(xmlGenericErrorContext,
7746                 "Reading %s entity content input\n", entity->name);
7747
7748     buf = xmlBufferCreate();
7749     if (buf == NULL) {
7750         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
7751                     "xmlLoadEntityContent parameter error");
7752         return(-1);
7753     }
7754
7755     input = xmlNewEntityInputStream(ctxt, entity);
7756     if (input == NULL) {
7757         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
7758                     "xmlLoadEntityContent input error");
7759         xmlBufferFree(buf);
7760         return(-1);
7761     }
7762
7763     /*
7764      * Push the entity as the current input, read char by char
7765      * saving to the buffer until the end of the entity or an error
7766      */
7767     if (xmlPushInput(ctxt, input) < 0) {
7768         xmlBufferFree(buf);
7769         return(-1);
7770     }
7771
7772     GROW;
7773     c = CUR_CHAR(l);
7774     while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
7775            (IS_CHAR(c))) {
7776         xmlBufferAdd(buf, ctxt->input->cur, l);
7777         if (count++ > 100) {
7778             count = 0;
7779             GROW;
7780         }
7781         NEXTL(l);
7782         c = CUR_CHAR(l);
7783     }
7784
7785     if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
7786         xmlPopInput(ctxt);
7787     } else if (!IS_CHAR(c)) {
7788         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
7789                           "xmlLoadEntityContent: invalid char value %d\n",
7790                           c);
7791         xmlBufferFree(buf);
7792         return(-1);
7793     }
7794     entity->content = buf->content;
7795     buf->content = NULL;
7796     xmlBufferFree(buf);
7797
7798     return(0);
7799 }
7800
7801 /**
7802  * xmlParseStringPEReference:
7803  * @ctxt:  an XML parser context
7804  * @str:  a pointer to an index in the string
7805  *
7806  * parse PEReference declarations
7807  *
7808  * [69] PEReference ::= '%' Name ';'
7809  *
7810  * [ WFC: No Recursion ]
7811  * A parsed entity must not contain a recursive
7812  * reference to itself, either directly or indirectly.
7813  *
7814  * [ WFC: Entity Declared ]
7815  * In a document without any DTD, a document with only an internal DTD
7816  * subset which contains no parameter entity references, or a document
7817  * with "standalone='yes'", ...  ... The declaration of a parameter
7818  * entity must precede any reference to it...
7819  *
7820  * [ VC: Entity Declared ]
7821  * In a document with an external subset or external parameter entities
7822  * with "standalone='no'", ...  ... The declaration of a parameter entity
7823  * must precede any reference to it...
7824  *
7825  * [ WFC: In DTD ]
7826  * Parameter-entity references may only appear in the DTD.
7827  * NOTE: misleading but this is handled.
7828  *
7829  * Returns the string of the entity content.
7830  *         str is updated to the current value of the index
7831  */
7832 static xmlEntityPtr
7833 xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
7834     const xmlChar *ptr;
7835     xmlChar cur;
7836     xmlChar *name;
7837     xmlEntityPtr entity = NULL;
7838
7839     if ((str == NULL) || (*str == NULL)) return(NULL);
7840     ptr = *str;
7841     cur = *ptr;
7842     if (cur != '%')
7843         return(NULL);
7844     ptr++;
7845     name = xmlParseStringName(ctxt, &ptr);
7846     if (name == NULL) {
7847         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7848                        "xmlParseStringPEReference: no name\n");
7849         *str = ptr;
7850         return(NULL);
7851     }
7852     cur = *ptr;
7853     if (cur != ';') {
7854         xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7855         xmlFree(name);
7856         *str = ptr;
7857         return(NULL);
7858     }
7859     ptr++;
7860
7861     /*
7862      * Increate the number of entity references parsed
7863      */
7864     ctxt->nbentities++;
7865
7866     /*
7867      * Request the entity from SAX
7868      */
7869     if ((ctxt->sax != NULL) &&
7870         (ctxt->sax->getParameterEntity != NULL))
7871         entity = ctxt->sax->getParameterEntity(ctxt->userData,
7872                                                name);
7873     if (entity == NULL) {
7874         /*
7875          * [ WFC: Entity Declared ]
7876          * In a document without any DTD, a document with only an
7877          * internal DTD subset which contains no parameter entity
7878          * references, or a document with "standalone='yes'", ...
7879          * ... The declaration of a parameter entity must precede
7880          * any reference to it...
7881          */
7882         if ((ctxt->standalone == 1) ||
7883             ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
7884             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7885                  "PEReference: %%%s; not found\n", name);
7886         } else {
7887             /*
7888              * [ VC: Entity Declared ]
7889              * In a document with an external subset or external
7890              * parameter entities with "standalone='no'", ...
7891              * ... The declaration of a parameter entity must
7892              * precede any reference to it...
7893              */
7894             xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7895                           "PEReference: %%%s; not found\n",
7896                           name, NULL);
7897             ctxt->valid = 0;
7898         }
7899     } else {
7900         /*
7901          * Internal checking in case the entity quest barfed
7902          */
7903         if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
7904             (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
7905             xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7906                           "%%%s; is not a parameter entity\n",
7907                           name, NULL);
7908         }
7909     }
7910     ctxt->hasPErefs = 1;
7911     xmlFree(name);
7912     *str = ptr;
7913     return(entity);
7914 }
7915
7916 /**
7917  * xmlParseDocTypeDecl:
7918  * @ctxt:  an XML parser context
7919  *
7920  * parse a DOCTYPE declaration
7921  *
7922  * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? 
7923  *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
7924  *
7925  * [ VC: Root Element Type ]
7926  * The Name in the document type declaration must match the element
7927  * type of the root element. 
7928  */
7929
7930 void
7931 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
7932     const xmlChar *name = NULL;
7933     xmlChar *ExternalID = NULL;
7934     xmlChar *URI = NULL;
7935
7936     /*
7937      * We know that '<!DOCTYPE' has been detected.
7938      */
7939     SKIP(9);
7940
7941     SKIP_BLANKS;
7942
7943     /*
7944      * Parse the DOCTYPE name.
7945      */
7946     name = xmlParseName(ctxt);
7947     if (name == NULL) {
7948         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7949                        "xmlParseDocTypeDecl : no DOCTYPE name !\n");
7950     }
7951     ctxt->intSubName = name;
7952
7953     SKIP_BLANKS;
7954
7955     /*
7956      * Check for SystemID and ExternalID
7957      */
7958     URI = xmlParseExternalID(ctxt, &ExternalID, 1);
7959
7960     if ((URI != NULL) || (ExternalID != NULL)) {
7961         ctxt->hasExternalSubset = 1;
7962     }
7963     ctxt->extSubURI = URI;
7964     ctxt->extSubSystem = ExternalID;
7965
7966     SKIP_BLANKS;
7967
7968     /*
7969      * Create and update the internal subset.
7970      */
7971     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
7972         (!ctxt->disableSAX))
7973         ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
7974
7975     /*
7976      * Is there any internal subset declarations ?
7977      * they are handled separately in xmlParseInternalSubset()
7978      */
7979     if (RAW == '[')
7980         return;
7981
7982     /*
7983      * We should be at the end of the DOCTYPE declaration.
7984      */
7985     if (RAW != '>') {
7986         xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
7987     }
7988     NEXT;
7989 }
7990
7991 /**
7992  * xmlParseInternalSubset:
7993  * @ctxt:  an XML parser context
7994  *
7995  * parse the internal subset declaration
7996  *
7997  * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
7998  */
7999
8000 static void
8001 xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8002     /*
8003      * Is there any DTD definition ?
8004      */
8005     if (RAW == '[') {
8006         ctxt->instate = XML_PARSER_DTD;
8007         NEXT;
8008         /*
8009          * Parse the succession of Markup declarations and 
8010          * PEReferences.
8011          * Subsequence (markupdecl | PEReference | S)*
8012          */
8013         while (RAW != ']') {
8014             const xmlChar *check = CUR_PTR;
8015             unsigned int cons = ctxt->input->consumed;
8016
8017             SKIP_BLANKS;
8018             xmlParseMarkupDecl(ctxt);
8019             xmlParsePEReference(ctxt);
8020
8021             /*
8022              * Pop-up of finished entities.
8023              */
8024             while ((RAW == 0) && (ctxt->inputNr > 1))
8025                 xmlPopInput(ctxt);
8026
8027             if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
8028                 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8029              "xmlParseInternalSubset: error detected in Markup declaration\n");
8030                 break;
8031             }
8032         }
8033         if (RAW == ']') { 
8034             NEXT;
8035             SKIP_BLANKS;
8036         }
8037     }
8038
8039     /*
8040      * We should be at the end of the DOCTYPE declaration.
8041      */
8042     if (RAW != '>') {
8043         xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8044     }
8045     NEXT;
8046 }
8047
8048 #ifdef LIBXML_SAX1_ENABLED
8049 /**
8050  * xmlParseAttribute:
8051  * @ctxt:  an XML parser context
8052  * @value:  a xmlChar ** used to store the value of the attribute
8053  *
8054  * parse an attribute
8055  *
8056  * [41] Attribute ::= Name Eq AttValue
8057  *
8058  * [ WFC: No External Entity References ]
8059  * Attribute values cannot contain direct or indirect entity references
8060  * to external entities.
8061  *
8062  * [ WFC: No < in Attribute Values ]
8063  * The replacement text of any entity referred to directly or indirectly in
8064  * an attribute value (other than "&lt;") must not contain a <. 
8065  * 
8066  * [ VC: Attribute Value Type ]
8067  * The attribute must have been declared; the value must be of the type
8068  * declared for it.
8069  *
8070  * [25] Eq ::= S? '=' S?
8071  *
8072  * With namespace:
8073  *
8074  * [NS 11] Attribute ::= QName Eq AttValue
8075  *
8076  * Also the case QName == xmlns:??? is handled independently as a namespace
8077  * definition.
8078  *
8079  * Returns the attribute name, and the value in *value.
8080  */
8081
8082 const xmlChar *
8083 xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8084     const xmlChar *name;
8085     xmlChar *val;
8086
8087     *value = NULL;
8088     GROW;
8089     name = xmlParseName(ctxt);
8090     if (name == NULL) {
8091         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8092                        "error parsing attribute name\n");
8093         return(NULL);
8094     }
8095
8096     /*
8097      * read the value
8098      */
8099     SKIP_BLANKS;
8100     if (RAW == '=') {
8101         NEXT;
8102         SKIP_BLANKS;
8103         val = xmlParseAttValue(ctxt);
8104         ctxt->instate = XML_PARSER_CONTENT;
8105     } else {
8106         xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8107                "Specification mandate value for attribute %s\n", name);
8108         return(NULL);
8109     }
8110
8111     /*
8112      * Check that xml:lang conforms to the specification
8113      * No more registered as an error, just generate a warning now
8114      * since this was deprecated in XML second edition
8115      */
8116     if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8117         if (!xmlCheckLanguageID(val)) {
8118             xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8119                           "Malformed value for xml:lang : %s\n",
8120                           val, NULL);
8121         }
8122     }
8123
8124     /*
8125      * Check that xml:space conforms to the specification
8126      */
8127     if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8128         if (xmlStrEqual(val, BAD_CAST "default"))
8129             *(ctxt->space) = 0;
8130         else if (xmlStrEqual(val, BAD_CAST "preserve"))
8131             *(ctxt->space) = 1;
8132         else {
8133                 xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8134 "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8135                                  val, NULL);
8136         }
8137     }
8138
8139     *value = val;
8140     return(name);
8141 }
8142
8143 /**
8144  * xmlParseStartTag:
8145  * @ctxt:  an XML parser context
8146  * 
8147  * parse a start of tag either for rule element or
8148  * EmptyElement. In both case we don't parse the tag closing chars.
8149  *
8150  * [40] STag ::= '<' Name (S Attribute)* S? '>'
8151  *
8152  * [ WFC: Unique Att Spec ]
8153  * No attribute name may appear more than once in the same start-tag or
8154  * empty-element tag. 
8155  *
8156  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8157  *
8158  * [ WFC: Unique Att Spec ]
8159  * No attribute name may appear more than once in the same start-tag or
8160  * empty-element tag. 
8161  *
8162  * With namespace:
8163  *
8164  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8165  *
8166  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8167  *
8168  * Returns the element name parsed
8169  */
8170
8171 const xmlChar *
8172 xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8173     const xmlChar *name;
8174     const xmlChar *attname;
8175     xmlChar *attvalue;
8176     const xmlChar **atts = ctxt->atts;
8177     int nbatts = 0;
8178     int maxatts = ctxt->maxatts;
8179     int i;
8180
8181     if (RAW != '<') return(NULL);
8182     NEXT1;
8183
8184     name = xmlParseName(ctxt);
8185     if (name == NULL) {
8186         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8187              "xmlParseStartTag: invalid element name\n");
8188         return(NULL);
8189     }
8190
8191     /*
8192      * Now parse the attributes, it ends up with the ending
8193      *
8194      * (S Attribute)* S?
8195      */
8196     SKIP_BLANKS;
8197     GROW;
8198
8199     while ((RAW != '>') && 
8200            ((RAW != '/') || (NXT(1) != '>')) &&
8201            (IS_BYTE_CHAR(RAW))) {
8202         const xmlChar *q = CUR_PTR;
8203         unsigned int cons = ctxt->input->consumed;
8204
8205         attname = xmlParseAttribute(ctxt, &attvalue);
8206         if ((attname != NULL) && (attvalue != NULL)) {
8207             /*
8208              * [ WFC: Unique Att Spec ]
8209              * No attribute name may appear more than once in the same
8210              * start-tag or empty-element tag. 
8211              */
8212             for (i = 0; i < nbatts;i += 2) {
8213                 if (xmlStrEqual(atts[i], attname)) {
8214                     xmlErrAttributeDup(ctxt, NULL, attname);
8215                     xmlFree(attvalue);
8216                     goto failed;
8217                 }
8218             }
8219             /*
8220              * Add the pair to atts
8221              */
8222             if (atts == NULL) {
8223                 maxatts = 22; /* allow for 10 attrs by default */
8224                 atts = (const xmlChar **)
8225                        xmlMalloc(maxatts * sizeof(xmlChar *));
8226                 if (atts == NULL) {
8227                     xmlErrMemory(ctxt, NULL);
8228                     if (attvalue != NULL)
8229                         xmlFree(attvalue);
8230                     goto failed;
8231                 }
8232                 ctxt->atts = atts;
8233                 ctxt->maxatts = maxatts;
8234             } else if (nbatts + 4 > maxatts) {
8235                 const xmlChar **n;
8236
8237                 maxatts *= 2;
8238                 n = (const xmlChar **) xmlRealloc((void *) atts,
8239                                              maxatts * sizeof(const xmlChar *));
8240                 if (n == NULL) {
8241                     xmlErrMemory(ctxt, NULL);
8242                     if (attvalue != NULL)
8243                         xmlFree(attvalue);
8244                     goto failed;
8245                 }
8246                 atts = n;
8247                 ctxt->atts = atts;
8248                 ctxt->maxatts = maxatts;
8249             }
8250             atts[nbatts++] = attname;
8251             atts[nbatts++] = attvalue;
8252             atts[nbatts] = NULL;
8253             atts[nbatts + 1] = NULL;
8254         } else {
8255             if (attvalue != NULL)
8256                 xmlFree(attvalue);
8257         }
8258
8259 failed:     
8260
8261         GROW
8262         if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8263             break;
8264         if (!IS_BLANK_CH(RAW)) {
8265             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8266                            "attributes construct error\n");
8267         }
8268         SKIP_BLANKS;
8269         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
8270             (attname == NULL) && (attvalue == NULL)) {
8271             xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8272                            "xmlParseStartTag: problem parsing attributes\n");
8273             break;
8274         }
8275         SHRINK;
8276         GROW;
8277     }
8278
8279     /*
8280      * SAX: Start of Element !
8281      */
8282     if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8283         (!ctxt->disableSAX)) {
8284         if (nbatts > 0)
8285             ctxt->sax->startElement(ctxt->userData, name, atts);
8286         else
8287             ctxt->sax->startElement(ctxt->userData, name, NULL);
8288     }
8289
8290     if (atts != NULL) {
8291         /* Free only the content strings */
8292         for (i = 1;i < nbatts;i+=2)
8293             if (atts[i] != NULL)
8294                xmlFree((xmlChar *) atts[i]);
8295     }
8296     return(name);
8297 }
8298
8299 /**
8300  * xmlParseEndTag1:
8301  * @ctxt:  an XML parser context
8302  * @line:  line of the start tag
8303  * @nsNr:  number of namespaces on the start tag
8304  *
8305  * parse an end of tag
8306  *
8307  * [42] ETag ::= '</' Name S? '>'
8308  *
8309  * With namespace
8310  *
8311  * [NS 9] ETag ::= '</' QName S? '>'
8312  */
8313
8314 static void
8315 xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8316     const xmlChar *name;
8317
8318     GROW;
8319     if ((RAW != '<') || (NXT(1) != '/')) {
8320         xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8321                        "xmlParseEndTag: '</' not found\n");
8322         return;
8323     }
8324     SKIP(2);
8325
8326     name = xmlParseNameAndCompare(ctxt,ctxt->name);
8327
8328     /*
8329      * We should definitely be at the ending "S? '>'" part
8330      */
8331     GROW;
8332     SKIP_BLANKS;
8333     if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8334         xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8335     } else
8336         NEXT1;
8337
8338     /*
8339      * [ WFC: Element Type Match ]
8340      * The Name in an element's end-tag must match the element type in the
8341      * start-tag. 
8342      *
8343      */
8344     if (name != (xmlChar*)1) {
8345         if (name == NULL) name = BAD_CAST "unparseable";
8346         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8347                      "Opening and ending tag mismatch: %s line %d and %s\n",
8348                                 ctxt->name, line, name);
8349     }
8350
8351     /*
8352      * SAX: End of Tag
8353      */
8354     if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8355         (!ctxt->disableSAX))
8356         ctxt->sax->endElement(ctxt->userData, ctxt->name);
8357
8358     namePop(ctxt);
8359     spacePop(ctxt);
8360     return;
8361 }
8362
8363 /**
8364  * xmlParseEndTag:
8365  * @ctxt:  an XML parser context
8366  *
8367  * parse an end of tag
8368  *
8369  * [42] ETag ::= '</' Name S? '>'
8370  *
8371  * With namespace
8372  *
8373  * [NS 9] ETag ::= '</' QName S? '>'
8374  */
8375
8376 void
8377 xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8378     xmlParseEndTag1(ctxt, 0);
8379 }
8380 #endif /* LIBXML_SAX1_ENABLED */
8381
8382 /************************************************************************
8383  *                                                                      *
8384  *                    SAX 2 specific operations                         *
8385  *                                                                      *
8386  ************************************************************************/
8387
8388 /*
8389  * xmlGetNamespace:
8390  * @ctxt:  an XML parser context
8391  * @prefix:  the prefix to lookup
8392  *
8393  * Lookup the namespace name for the @prefix (which ca be NULL)
8394  * The prefix must come from the @ctxt->dict dictionnary
8395  *
8396  * Returns the namespace name or NULL if not bound
8397  */
8398 static const xmlChar *
8399 xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8400     int i;
8401
8402     if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8403     for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8404         if (ctxt->nsTab[i] == prefix) {
8405             if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8406                 return(NULL);
8407             return(ctxt->nsTab[i + 1]);
8408         }
8409     return(NULL);
8410 }
8411
8412 /**
8413  * xmlParseQName:
8414  * @ctxt:  an XML parser context
8415  * @prefix:  pointer to store the prefix part
8416  *
8417  * parse an XML Namespace QName
8418  *
8419  * [6]  QName  ::= (Prefix ':')? LocalPart
8420  * [7]  Prefix  ::= NCName
8421  * [8]  LocalPart  ::= NCName
8422  *
8423  * Returns the Name parsed or NULL
8424  */
8425
8426 static const xmlChar *
8427 xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8428     const xmlChar *l, *p;
8429
8430     GROW;
8431
8432     l = xmlParseNCName(ctxt);
8433     if (l == NULL) {
8434         if (CUR == ':') {
8435             l = xmlParseName(ctxt);
8436             if (l != NULL) {
8437                 xmlNsErr(ctxt, XML_NS_ERR_QNAME, 
8438                          "Failed to parse QName '%s'\n", l, NULL, NULL);
8439                 *prefix = NULL;
8440                 return(l);
8441             }
8442         }
8443         return(NULL);
8444     }
8445     if (CUR == ':') {
8446         NEXT;
8447         p = l;
8448         l = xmlParseNCName(ctxt);
8449         if (l == NULL) {
8450             xmlChar *tmp;
8451
8452             xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8453                      "Failed to parse QName '%s:'\n", p, NULL, NULL);
8454             l = xmlParseNmtoken(ctxt);
8455             if (l == NULL)
8456                 tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8457             else {
8458                 tmp = xmlBuildQName(l, p, NULL, 0);
8459                 xmlFree((char *)l);
8460             }
8461             p = xmlDictLookup(ctxt->dict, tmp, -1);
8462             if (tmp != NULL) xmlFree(tmp);
8463             *prefix = NULL;
8464             return(p);
8465         }
8466         if (CUR == ':') {
8467             xmlChar *tmp;
8468
8469             xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8470                      "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8471             NEXT;
8472             tmp = (xmlChar *) xmlParseName(ctxt);
8473             if (tmp != NULL) {
8474                 tmp = xmlBuildQName(tmp, l, NULL, 0);
8475                 l = xmlDictLookup(ctxt->dict, tmp, -1);
8476                 if (tmp != NULL) xmlFree(tmp);
8477                 *prefix = p;
8478                 return(l);
8479             }
8480             tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8481             l = xmlDictLookup(ctxt->dict, tmp, -1);
8482             if (tmp != NULL) xmlFree(tmp);
8483             *prefix = p;
8484             return(l);
8485         }
8486         *prefix = p;
8487     } else
8488         *prefix = NULL;
8489     return(l);
8490 }
8491
8492 /**
8493  * xmlParseQNameAndCompare:
8494  * @ctxt:  an XML parser context
8495  * @name:  the localname
8496  * @prefix:  the prefix, if any.
8497  *
8498  * parse an XML name and compares for match
8499  * (specialized for endtag parsing)
8500  *
8501  * Returns NULL for an illegal name, (xmlChar*) 1 for success
8502  * and the name for mismatch
8503  */
8504
8505 static const xmlChar *
8506 xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8507                         xmlChar const *prefix) {
8508     const xmlChar *cmp;
8509     const xmlChar *in;
8510     const xmlChar *ret;
8511     const xmlChar *prefix2;
8512
8513     if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8514
8515     GROW;
8516     in = ctxt->input->cur;
8517
8518     cmp = prefix;
8519     while (*in != 0 && *in == *cmp) {
8520         ++in;
8521         ++cmp;
8522     }
8523     if ((*cmp == 0) && (*in == ':')) {
8524         in++;
8525         cmp = name;
8526         while (*in != 0 && *in == *cmp) {
8527             ++in;
8528             ++cmp;
8529         }
8530         if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8531             /* success */
8532             ctxt->input->cur = in;
8533             return((const xmlChar*) 1);
8534         }
8535     }
8536     /*
8537      * all strings coms from the dictionary, equality can be done directly
8538      */
8539     ret = xmlParseQName (ctxt, &prefix2);
8540     if ((ret == name) && (prefix == prefix2))
8541         return((const xmlChar*) 1);
8542     return ret;
8543 }
8544
8545 /**
8546  * xmlParseAttValueInternal:
8547  * @ctxt:  an XML parser context
8548  * @len:  attribute len result
8549  * @alloc:  whether the attribute was reallocated as a new string
8550  * @normalize:  if 1 then further non-CDATA normalization must be done
8551  *
8552  * parse a value for an attribute.
8553  * NOTE: if no normalization is needed, the routine will return pointers
8554  *       directly from the data buffer.
8555  *
8556  * 3.3.3 Attribute-Value Normalization:
8557  * Before the value of an attribute is passed to the application or
8558  * checked for validity, the XML processor must normalize it as follows: 
8559  * - a character reference is processed by appending the referenced
8560  *   character to the attribute value
8561  * - an entity reference is processed by recursively processing the
8562  *   replacement text of the entity 
8563  * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
8564  *   appending #x20 to the normalized value, except that only a single
8565  *   #x20 is appended for a "#xD#xA" sequence that is part of an external
8566  *   parsed entity or the literal entity value of an internal parsed entity 
8567  * - other characters are processed by appending them to the normalized value 
8568  * If the declared value is not CDATA, then the XML processor must further
8569  * process the normalized attribute value by discarding any leading and
8570  * trailing space (#x20) characters, and by replacing sequences of space
8571  * (#x20) characters by a single space (#x20) character.  
8572  * All attributes for which no declaration has been read should be treated
8573  * by a non-validating parser as if declared CDATA.
8574  *
8575  * Returns the AttValue parsed or NULL. The value has to be freed by the
8576  *     caller if it was copied, this can be detected by val[*len] == 0.
8577  */
8578
8579 static xmlChar *
8580 xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
8581                          int normalize)
8582 {
8583     xmlChar limit = 0;
8584     const xmlChar *in = NULL, *start, *end, *last;
8585     xmlChar *ret = NULL;
8586
8587     GROW;
8588     in = (xmlChar *) CUR_PTR;
8589     if (*in != '"' && *in != '\'') {
8590         xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
8591         return (NULL);
8592     }
8593     ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
8594
8595     /*
8596      * try to handle in this routine the most common case where no
8597      * allocation of a new string is required and where content is
8598      * pure ASCII.
8599      */
8600     limit = *in++;
8601     end = ctxt->input->end;
8602     start = in;
8603     if (in >= end) {
8604         const xmlChar *oldbase = ctxt->input->base;
8605         GROW;
8606         if (oldbase != ctxt->input->base) {
8607             long delta = ctxt->input->base - oldbase;
8608             start = start + delta;
8609             in = in + delta;
8610         }
8611         end = ctxt->input->end;
8612     }
8613     if (normalize) {
8614         /*
8615          * Skip any leading spaces
8616          */
8617         while ((in < end) && (*in != limit) && 
8618                ((*in == 0x20) || (*in == 0x9) ||
8619                 (*in == 0xA) || (*in == 0xD))) {
8620             in++;
8621             start = in;
8622             if (in >= end) {
8623                 const xmlChar *oldbase = ctxt->input->base;
8624                 GROW;
8625                 if (oldbase != ctxt->input->base) {
8626                     long delta = ctxt->input->base - oldbase;
8627                     start = start + delta;
8628                     in = in + delta;
8629                 }
8630                 end = ctxt->input->end;
8631             }
8632         }
8633         while ((in < end) && (*in != limit) && (*in >= 0x20) &&
8634                (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
8635             if ((*in++ == 0x20) && (*in == 0x20)) break;
8636             if (in >= end) {
8637                 const xmlChar *oldbase = ctxt->input->base;
8638                 GROW;
8639                 if (oldbase != ctxt->input->base) {
8640                     long delta = ctxt->input->base - oldbase;
8641                     start = start + delta;
8642                     in = in + delta;
8643                 }
8644                 end = ctxt->input->end;
8645             }
8646         }
8647         last = in;
8648         /*
8649          * skip the trailing blanks
8650          */
8651         while ((last[-1] == 0x20) && (last > start)) last--;
8652         while ((in < end) && (*in != limit) && 
8653                ((*in == 0x20) || (*in == 0x9) ||
8654                 (*in == 0xA) || (*in == 0xD))) {
8655             in++;
8656             if (in >= end) {
8657                 const xmlChar *oldbase = ctxt->input->base;
8658                 GROW;
8659                 if (oldbase != ctxt->input->base) {
8660                     long delta = ctxt->input->base - oldbase;
8661                     start = start + delta;
8662                     in = in + delta;
8663                     last = last + delta;
8664                 }
8665                 end = ctxt->input->end;
8666             }
8667         }
8668         if (*in != limit) goto need_complex;
8669     } else {
8670         while ((in < end) && (*in != limit) && (*in >= 0x20) &&
8671                (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
8672             in++;
8673             if (in >= end) {
8674                 const xmlChar *oldbase = ctxt->input->base;
8675                 GROW;
8676                 if (oldbase != ctxt->input->base) {
8677                     long delta = ctxt->input->base - oldbase;
8678                     start = start + delta;
8679                     in = in + delta;
8680                 }
8681                 end = ctxt->input->end;
8682             }
8683         }
8684         last = in;
8685         if (*in != limit) goto need_complex;
8686     }
8687     in++;
8688     if (len != NULL) {
8689         *len = last - start;
8690         ret = (xmlChar *) start;
8691     } else {
8692         if (alloc) *alloc = 1;
8693         ret = xmlStrndup(start, last - start);
8694     }
8695     CUR_PTR = in;
8696     if (alloc) *alloc = 0;
8697     return ret;
8698 need_complex:
8699     if (alloc) *alloc = 1;
8700     return xmlParseAttValueComplex(ctxt, len, normalize);
8701 }
8702
8703 /**
8704  * xmlParseAttribute2:
8705  * @ctxt:  an XML parser context
8706  * @pref:  the element prefix
8707  * @elem:  the element name
8708  * @prefix:  a xmlChar ** used to store the value of the attribute prefix
8709  * @value:  a xmlChar ** used to store the value of the attribute
8710  * @len:  an int * to save the length of the attribute
8711  * @alloc:  an int * to indicate if the attribute was allocated
8712  *
8713  * parse an attribute in the new SAX2 framework.
8714  *
8715  * Returns the attribute name, and the value in *value, .
8716  */
8717
8718 static const xmlChar *
8719 xmlParseAttribute2(xmlParserCtxtPtr ctxt,
8720                    const xmlChar * pref, const xmlChar * elem,
8721                    const xmlChar ** prefix, xmlChar ** value,
8722                    int *len, int *alloc)
8723 {
8724     const xmlChar *name;
8725     xmlChar *val, *internal_val = NULL;
8726     int normalize = 0;
8727
8728     *value = NULL;
8729     GROW;
8730     name = xmlParseQName(ctxt, prefix);
8731     if (name == NULL) {
8732         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8733                        "error parsing attribute name\n");
8734         return (NULL);
8735     }
8736
8737     /*
8738      * get the type if needed
8739      */
8740     if (ctxt->attsSpecial != NULL) {
8741         int type;
8742
8743         type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
8744                                             pref, elem, *prefix, name);
8745         if (type != 0)
8746             normalize = 1;
8747     }
8748
8749     /*
8750      * read the value
8751      */
8752     SKIP_BLANKS;
8753     if (RAW == '=') {
8754         NEXT;
8755         SKIP_BLANKS;
8756         val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
8757         if (normalize) {
8758             /*
8759              * Sometimes a second normalisation pass for spaces is needed
8760              * but that only happens if charrefs or entities refernces
8761              * have been used in the attribute value, i.e. the attribute
8762              * value have been extracted in an allocated string already.
8763              */
8764             if (*alloc) {
8765                 const xmlChar *val2;
8766
8767                 val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
8768                 if ((val2 != NULL) && (val2 != val)) {
8769                     xmlFree(val);
8770                     val = (xmlChar *) val2;
8771                 }
8772             }
8773         }
8774         ctxt->instate = XML_PARSER_CONTENT;
8775     } else {
8776         xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8777                           "Specification mandate value for attribute %s\n",
8778                           name);
8779         return (NULL);
8780     }
8781
8782     if (*prefix == ctxt->str_xml) {
8783         /*
8784          * Check that xml:lang conforms to the specification
8785          * No more registered as an error, just generate a warning now
8786          * since this was deprecated in XML second edition
8787          */
8788         if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
8789             internal_val = xmlStrndup(val, *len);
8790             if (!xmlCheckLanguageID(internal_val)) {
8791                 xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8792                               "Malformed value for xml:lang : %s\n",
8793                               internal_val, NULL);
8794             }
8795         }
8796
8797         /*
8798          * Check that xml:space conforms to the specification
8799          */
8800         if (xmlStrEqual(name, BAD_CAST "space")) {
8801             internal_val = xmlStrndup(val, *len);
8802             if (xmlStrEqual(internal_val, BAD_CAST "default"))
8803                 *(ctxt->space) = 0;
8804             else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
8805                 *(ctxt->space) = 1;
8806             else {
8807                 xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8808                               "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8809                               internal_val, NULL);
8810             }
8811         }
8812         if (internal_val) {
8813             xmlFree(internal_val);
8814         }
8815     }
8816
8817     *value = val;
8818     return (name);
8819 }
8820 /**
8821  * xmlParseStartTag2:
8822  * @ctxt:  an XML parser context
8823  * 
8824  * parse a start of tag either for rule element or
8825  * EmptyElement. In both case we don't parse the tag closing chars.
8826  * This routine is called when running SAX2 parsing
8827  *
8828  * [40] STag ::= '<' Name (S Attribute)* S? '>'
8829  *
8830  * [ WFC: Unique Att Spec ]
8831  * No attribute name may appear more than once in the same start-tag or
8832  * empty-element tag. 
8833  *
8834  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8835  *
8836  * [ WFC: Unique Att Spec ]
8837  * No attribute name may appear more than once in the same start-tag or
8838  * empty-element tag. 
8839  *
8840  * With namespace:
8841  *
8842  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8843  *
8844  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8845  *
8846  * Returns the element name parsed
8847  */
8848
8849 static const xmlChar *
8850 xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
8851                   const xmlChar **URI, int *tlen) {
8852     const xmlChar *localname;
8853     const xmlChar *prefix;
8854     const xmlChar *attname;
8855     const xmlChar *aprefix;
8856     const xmlChar *nsname;
8857     xmlChar *attvalue;
8858     const xmlChar **atts = ctxt->atts;
8859     int maxatts = ctxt->maxatts;
8860     int nratts, nbatts, nbdef;
8861     int i, j, nbNs, attval, oldline, oldcol;
8862     const xmlChar *base;
8863     unsigned long cur;
8864     int nsNr = ctxt->nsNr;
8865
8866     if (RAW != '<') return(NULL);
8867     NEXT1;
8868
8869     /*
8870      * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
8871      *       point since the attribute values may be stored as pointers to
8872      *       the buffer and calling SHRINK would destroy them !
8873      *       The Shrinking is only possible once the full set of attribute
8874      *       callbacks have been done.
8875      */
8876 reparse:
8877     SHRINK;
8878     base = ctxt->input->base;
8879     cur = ctxt->input->cur - ctxt->input->base;
8880     oldline = ctxt->input->line;
8881     oldcol = ctxt->input->col;
8882     nbatts = 0;
8883     nratts = 0;
8884     nbdef = 0;
8885     nbNs = 0;
8886     attval = 0;
8887     /* Forget any namespaces added during an earlier parse of this element. */
8888     ctxt->nsNr = nsNr;
8889
8890     localname = xmlParseQName(ctxt, &prefix);
8891     if (localname == NULL) {
8892         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8893                        "StartTag: invalid element name\n");
8894         return(NULL);
8895     }
8896     *tlen = ctxt->input->cur - ctxt->input->base - cur;
8897
8898     /*
8899      * Now parse the attributes, it ends up with the ending
8900      *
8901      * (S Attribute)* S?
8902      */
8903     SKIP_BLANKS;
8904     GROW;
8905     if (ctxt->input->base != base) goto base_changed;
8906
8907     while ((RAW != '>') && 
8908            ((RAW != '/') || (NXT(1) != '>')) &&
8909            (IS_BYTE_CHAR(RAW))) {
8910         const xmlChar *q = CUR_PTR;
8911         unsigned int cons = ctxt->input->consumed;
8912         int len = -1, alloc = 0;
8913
8914         attname = xmlParseAttribute2(ctxt, prefix, localname,
8915                                      &aprefix, &attvalue, &len, &alloc);
8916         if (ctxt->input->base != base) {
8917             if ((attvalue != NULL) && (alloc != 0))
8918                 xmlFree(attvalue);
8919             attvalue = NULL;
8920             goto base_changed;
8921         }
8922         if ((attname != NULL) && (attvalue != NULL)) {
8923             if (len < 0) len = xmlStrlen(attvalue);
8924             if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
8925                 const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
8926                 xmlURIPtr uri;
8927
8928                 if (*URL != 0) {
8929                     uri = xmlParseURI((const char *) URL);
8930                     if (uri == NULL) {
8931                         xmlNsErr(ctxt, XML_WAR_NS_URI,
8932                                  "xmlns: '%s' is not a valid URI\n",
8933                                            URL, NULL, NULL);
8934                     } else {
8935                         if (uri->scheme == NULL) {
8936                             xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
8937                                       "xmlns: URI %s is not absolute\n",
8938                                       URL, NULL, NULL);
8939                         }
8940                         xmlFreeURI(uri);
8941                     }
8942                     if (URL == ctxt->str_xml_ns) {
8943                         if (attname != ctxt->str_xml) {
8944                             xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
8945                          "xml namespace URI cannot be the default namespace\n",
8946                                      NULL, NULL, NULL);
8947                         }
8948                         goto skip_default_ns;
8949                     }
8950                     if ((len == 29) &&
8951                         (xmlStrEqual(URL,
8952                                  BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
8953                         xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
8954                              "reuse of the xmlns namespace name is forbidden\n",
8955                                  NULL, NULL, NULL);
8956                         goto skip_default_ns;
8957                     }
8958                 }
8959                 /*
8960                  * check that it's not a defined namespace
8961                  */
8962                 for (j = 1;j <= nbNs;j++)
8963                     if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
8964                         break;
8965                 if (j <= nbNs)
8966                     xmlErrAttributeDup(ctxt, NULL, attname);
8967                 else
8968                     if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
8969 skip_default_ns:
8970                 if (alloc != 0) xmlFree(attvalue);
8971                 SKIP_BLANKS;
8972                 continue;
8973             }
8974             if (aprefix == ctxt->str_xmlns) {
8975                 const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
8976                 xmlURIPtr uri;
8977
8978                 if (attname == ctxt->str_xml) {
8979                     if (URL != ctxt->str_xml_ns) {
8980                         xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
8981                                  "xml namespace prefix mapped to wrong URI\n",
8982                                  NULL, NULL, NULL);
8983                     }
8984                     /*
8985                      * Do not keep a namespace definition node
8986                      */
8987                     goto skip_ns;
8988                 }
8989                 if (URL == ctxt->str_xml_ns) {
8990                     if (attname != ctxt->str_xml) {
8991                         xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
8992                                  "xml namespace URI mapped to wrong prefix\n",
8993                                  NULL, NULL, NULL);
8994                     }
8995                     goto skip_ns;
8996                 }
8997                 if (attname == ctxt->str_xmlns) {
8998                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
8999                              "redefinition of the xmlns prefix is forbidden\n",
9000                              NULL, NULL, NULL);
9001                     goto skip_ns;
9002                 }
9003                 if ((len == 29) &&
9004                     (xmlStrEqual(URL,
9005                                  BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9006                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9007                              "reuse of the xmlns namespace name is forbidden\n",
9008                              NULL, NULL, NULL);
9009                     goto skip_ns;
9010                 }
9011                 if ((URL == NULL) || (URL[0] == 0)) {
9012                     xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9013                              "xmlns:%s: Empty XML namespace is not allowed\n",
9014                                   attname, NULL, NULL);
9015                     goto skip_ns;
9016                 } else {
9017                     uri = xmlParseURI((const char *) URL);
9018                     if (uri == NULL) {
9019                         xmlNsErr(ctxt, XML_WAR_NS_URI,
9020                              "xmlns:%s: '%s' is not a valid URI\n",
9021                                            attname, URL, NULL);
9022                     } else {
9023                         if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9024                             xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9025                                       "xmlns:%s: URI %s is not absolute\n",
9026                                       attname, URL, NULL);
9027                         }
9028                         xmlFreeURI(uri);
9029                     }
9030                 }
9031
9032                 /*
9033                  * check that it's not a defined namespace
9034                  */
9035                 for (j = 1;j <= nbNs;j++)
9036                     if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9037                         break;
9038                 if (j <= nbNs)
9039                     xmlErrAttributeDup(ctxt, aprefix, attname);
9040                 else
9041                     if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9042 skip_ns:
9043                 if (alloc != 0) xmlFree(attvalue);
9044                 SKIP_BLANKS;
9045                 if (ctxt->input->base != base) goto base_changed;
9046                 continue;
9047             }
9048
9049             /*
9050              * Add the pair to atts
9051              */
9052             if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9053                 if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9054                     if (attvalue[len] == 0)
9055                         xmlFree(attvalue);
9056                     goto failed;
9057                 }
9058                 maxatts = ctxt->maxatts;
9059                 atts = ctxt->atts;
9060             }
9061             ctxt->attallocs[nratts++] = alloc;
9062             atts[nbatts++] = attname;
9063             atts[nbatts++] = aprefix;
9064             atts[nbatts++] = NULL; /* the URI will be fetched later */
9065             atts[nbatts++] = attvalue;
9066             attvalue += len;
9067             atts[nbatts++] = attvalue;
9068             /*
9069              * tag if some deallocation is needed
9070              */
9071             if (alloc != 0) attval = 1;
9072         } else {
9073             if ((attvalue != NULL) && (attvalue[len] == 0))
9074                 xmlFree(attvalue);
9075         }
9076
9077 failed:
9078
9079         GROW
9080         if (ctxt->input->base != base) goto base_changed;
9081         if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9082             break;
9083         if (!IS_BLANK_CH(RAW)) {
9084             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9085                            "attributes construct error\n");
9086             break;
9087         }
9088         SKIP_BLANKS;
9089         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
9090             (attname == NULL) && (attvalue == NULL)) {
9091             xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9092                  "xmlParseStartTag: problem parsing attributes\n");
9093             break;
9094         }
9095         GROW;
9096         if (ctxt->input->base != base) goto base_changed;
9097     }
9098
9099     /*
9100      * The attributes defaulting
9101      */
9102     if (ctxt->attsDefault != NULL) {
9103         xmlDefAttrsPtr defaults;
9104
9105         defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9106         if (defaults != NULL) {
9107             for (i = 0;i < defaults->nbAttrs;i++) {
9108                 attname = defaults->values[5 * i];
9109                 aprefix = defaults->values[5 * i + 1];
9110
9111                 /*
9112                  * special work for namespaces defaulted defs
9113                  */
9114                 if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9115                     /*
9116                      * check that it's not a defined namespace
9117                      */
9118                     for (j = 1;j <= nbNs;j++)
9119                         if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9120                             break;
9121                     if (j <= nbNs) continue;
9122
9123                     nsname = xmlGetNamespace(ctxt, NULL);
9124                     if (nsname != defaults->values[5 * i + 2]) {
9125                         if (nsPush(ctxt, NULL,
9126                                    defaults->values[5 * i + 2]) > 0)
9127                             nbNs++;
9128                     }
9129                 } else if (aprefix == ctxt->str_xmlns) {
9130                     /*
9131                      * check that it's not a defined namespace
9132                      */
9133                     for (j = 1;j <= nbNs;j++)
9134                         if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9135                             break;
9136                     if (j <= nbNs) continue;
9137
9138                     nsname = xmlGetNamespace(ctxt, attname);
9139                     if (nsname != defaults->values[2]) {
9140                         if (nsPush(ctxt, attname,
9141                                    defaults->values[5 * i + 2]) > 0)
9142                             nbNs++;
9143                     }
9144                 } else {
9145                     /*
9146                      * check that it's not a defined attribute
9147                      */
9148                     for (j = 0;j < nbatts;j+=5) {
9149                         if ((attname == atts[j]) && (aprefix == atts[j+1]))
9150                             break;
9151                     }
9152                     if (j < nbatts) continue;
9153
9154                     if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9155                         if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9156                             return(NULL);
9157                         }
9158                         maxatts = ctxt->maxatts;
9159                         atts = ctxt->atts;
9160                     }
9161                     atts[nbatts++] = attname;
9162                     atts[nbatts++] = aprefix;
9163                     if (aprefix == NULL)
9164                         atts[nbatts++] = NULL;
9165                     else
9166                         atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9167                     atts[nbatts++] = defaults->values[5 * i + 2];
9168                     atts[nbatts++] = defaults->values[5 * i + 3];
9169                     if ((ctxt->standalone == 1) &&
9170                         (defaults->values[5 * i + 4] != NULL)) {
9171                         xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED, 
9172           "standalone: attribute %s on %s defaulted from external subset\n",
9173                                          attname, localname);
9174                     }
9175                     nbdef++;
9176                 }
9177             }
9178         }
9179     }
9180
9181     /*
9182      * The attributes checkings
9183      */
9184     for (i = 0; i < nbatts;i += 5) {
9185         /*
9186         * The default namespace does not apply to attribute names.
9187         */
9188         if (atts[i + 1] != NULL) {
9189             nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9190             if (nsname == NULL) {
9191                 xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9192                     "Namespace prefix %s for %s on %s is not defined\n",
9193                     atts[i + 1], atts[i], localname);
9194             }
9195             atts[i + 2] = nsname;
9196         } else
9197             nsname = NULL;
9198         /*
9199          * [ WFC: Unique Att Spec ]
9200          * No attribute name may appear more than once in the same
9201          * start-tag or empty-element tag. 
9202          * As extended by the Namespace in XML REC.
9203          */
9204         for (j = 0; j < i;j += 5) {
9205             if (atts[i] == atts[j]) {
9206                 if (atts[i+1] == atts[j+1]) {
9207                     xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9208                     break;
9209                 }
9210                 if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9211                     xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9212                              "Namespaced Attribute %s in '%s' redefined\n",
9213                              atts[i], nsname, NULL);
9214                     break;
9215                 }
9216             }
9217         }
9218     }
9219
9220     nsname = xmlGetNamespace(ctxt, prefix);
9221     if ((prefix != NULL) && (nsname == NULL)) {
9222         xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9223                  "Namespace prefix %s on %s is not defined\n",
9224                  prefix, localname, NULL);
9225     }
9226     *pref = prefix;
9227     *URI = nsname;
9228
9229     /*
9230      * SAX: Start of Element !
9231      */
9232     if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9233         (!ctxt->disableSAX)) {
9234         if (nbNs > 0)
9235             ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9236                           nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9237                           nbatts / 5, nbdef, atts);
9238         else
9239             ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9240                           nsname, 0, NULL, nbatts / 5, nbdef, atts);
9241     }
9242
9243     /*
9244      * Free up attribute allocated strings if needed
9245      */
9246     if (attval != 0) {
9247         for (i = 3,j = 0; j < nratts;i += 5,j++)
9248             if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9249                 xmlFree((xmlChar *) atts[i]);
9250     }
9251
9252     return(localname);
9253
9254 base_changed:
9255     /*
9256      * the attribute strings are valid iif the base didn't changed
9257      */
9258     if (attval != 0) {
9259         for (i = 3,j = 0; j < nratts;i += 5,j++)
9260             if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9261                 xmlFree((xmlChar *) atts[i]);
9262     }
9263     ctxt->input->cur = ctxt->input->base + cur;
9264     ctxt->input->line = oldline;
9265     ctxt->input->col = oldcol;
9266     if (ctxt->wellFormed == 1) {
9267         goto reparse;
9268     }
9269     return(NULL);
9270 }
9271
9272 /**
9273  * xmlParseEndTag2:
9274  * @ctxt:  an XML parser context
9275  * @line:  line of the start tag
9276  * @nsNr:  number of namespaces on the start tag
9277  *
9278  * parse an end of tag
9279  *
9280  * [42] ETag ::= '</' Name S? '>'
9281  *
9282  * With namespace
9283  *
9284  * [NS 9] ETag ::= '</' QName S? '>'
9285  */
9286
9287 static void
9288 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
9289                 const xmlChar *URI, int line, int nsNr, int tlen) {
9290     const xmlChar *name;
9291
9292     GROW;
9293     if ((RAW != '<') || (NXT(1) != '/')) {
9294         xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9295         return;
9296     }
9297     SKIP(2);
9298
9299     if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
9300         if (ctxt->input->cur[tlen] == '>') {
9301             ctxt->input->cur += tlen + 1;
9302             goto done;
9303         }
9304         ctxt->input->cur += tlen;
9305         name = (xmlChar*)1;
9306     } else {
9307         if (prefix == NULL)
9308             name = xmlParseNameAndCompare(ctxt, ctxt->name);
9309         else
9310             name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
9311     }
9312
9313     /*
9314      * We should definitely be at the ending "S? '>'" part
9315      */
9316     GROW;
9317     SKIP_BLANKS;
9318     if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9319         xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9320     } else
9321         NEXT1;
9322
9323     /*
9324      * [ WFC: Element Type Match ]
9325      * The Name in an element's end-tag must match the element type in the
9326      * start-tag. 
9327      *
9328      */
9329     if (name != (xmlChar*)1) {
9330         if (name == NULL) name = BAD_CAST "unparseable";
9331         if ((line == 0) && (ctxt->node != NULL))
9332             line = ctxt->node->line;
9333         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9334                      "Opening and ending tag mismatch: %s line %d and %s\n",
9335                                 ctxt->name, line, name);
9336     }
9337
9338     /*
9339      * SAX: End of Tag
9340      */
9341 done:
9342     if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9343         (!ctxt->disableSAX))
9344         ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
9345
9346     spacePop(ctxt);
9347     if (nsNr != 0)
9348         nsPop(ctxt, nsNr);
9349     return;
9350 }
9351
9352 /**
9353  * xmlParseCDSect:
9354  * @ctxt:  an XML parser context
9355  * 
9356  * Parse escaped pure raw content.
9357  *
9358  * [18] CDSect ::= CDStart CData CDEnd
9359  *
9360  * [19] CDStart ::= '<![CDATA['
9361  *
9362  * [20] Data ::= (Char* - (Char* ']]>' Char*))
9363  *
9364  * [21] CDEnd ::= ']]>'
9365  */
9366 void
9367 xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9368     xmlChar *buf = NULL;
9369     int len = 0;
9370     int size = XML_PARSER_BUFFER_SIZE;
9371     int r, rl;
9372     int s, sl;
9373     int cur, l;
9374     int count = 0;
9375
9376     /* Check 2.6.0 was NXT(0) not RAW */
9377     if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9378         SKIP(9);
9379     } else
9380         return;
9381
9382     ctxt->instate = XML_PARSER_CDATA_SECTION;
9383     r = CUR_CHAR(rl);
9384     if (!IS_CHAR(r)) {
9385         xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9386         ctxt->instate = XML_PARSER_CONTENT;
9387         return;
9388     }
9389     NEXTL(rl);
9390     s = CUR_CHAR(sl);
9391     if (!IS_CHAR(s)) {
9392         xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9393         ctxt->instate = XML_PARSER_CONTENT;
9394         return;
9395     }
9396     NEXTL(sl);
9397     cur = CUR_CHAR(l);
9398     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
9399     if (buf == NULL) {
9400         xmlErrMemory(ctxt, NULL);
9401         return;
9402     }
9403     while (IS_CHAR(cur) &&
9404            ((r != ']') || (s != ']') || (cur != '>'))) {
9405         if (len + 5 >= size) {
9406             xmlChar *tmp;
9407
9408             size *= 2;
9409             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
9410             if (tmp == NULL) {
9411                 xmlFree(buf);
9412                 xmlErrMemory(ctxt, NULL);
9413                 return;
9414             }
9415             buf = tmp;
9416         }
9417         COPY_BUF(rl,buf,len,r);
9418         r = s;
9419         rl = sl;
9420         s = cur;
9421         sl = l;
9422         count++;
9423         if (count > 50) {
9424             GROW;
9425             count = 0;
9426         }
9427         NEXTL(l);
9428         cur = CUR_CHAR(l);
9429     }
9430     buf[len] = 0;
9431     ctxt->instate = XML_PARSER_CONTENT;
9432     if (cur != '>') {
9433         xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9434                              "CData section not finished\n%.50s\n", buf);
9435         xmlFree(buf);
9436         return;
9437     }
9438     NEXTL(l);
9439
9440     /*
9441      * OK the buffer is to be consumed as cdata.
9442      */
9443     if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9444         if (ctxt->sax->cdataBlock != NULL)
9445             ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9446         else if (ctxt->sax->characters != NULL)
9447             ctxt->sax->characters(ctxt->userData, buf, len);
9448     }
9449     xmlFree(buf);
9450 }
9451
9452 /**
9453  * xmlParseContent:
9454  * @ctxt:  an XML parser context
9455  *
9456  * Parse a content:
9457  *
9458  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
9459  */
9460
9461 void
9462 xmlParseContent(xmlParserCtxtPtr ctxt) {
9463     GROW;
9464     while ((RAW != 0) &&
9465            ((RAW != '<') || (NXT(1) != '/')) &&
9466            (ctxt->instate != XML_PARSER_EOF)) {
9467         const xmlChar *test = CUR_PTR;
9468         unsigned int cons = ctxt->input->consumed;
9469         const xmlChar *cur = ctxt->input->cur;
9470
9471         /*
9472          * First case : a Processing Instruction.
9473          */
9474         if ((*cur == '<') && (cur[1] == '?')) {
9475             xmlParsePI(ctxt);
9476         }
9477
9478         /*
9479          * Second case : a CDSection
9480          */
9481         /* 2.6.0 test was *cur not RAW */
9482         else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9483             xmlParseCDSect(ctxt);
9484         }
9485
9486         /*
9487          * Third case :  a comment
9488          */
9489         else if ((*cur == '<') && (NXT(1) == '!') &&
9490                  (NXT(2) == '-') && (NXT(3) == '-')) {
9491             xmlParseComment(ctxt);
9492             ctxt->instate = XML_PARSER_CONTENT;
9493         }
9494
9495         /*
9496          * Fourth case :  a sub-element.
9497          */
9498         else if (*cur == '<') {
9499             xmlParseElement(ctxt);
9500         }
9501
9502         /*
9503          * Fifth case : a reference. If if has not been resolved,
9504          *    parsing returns it's Name, create the node 
9505          */
9506
9507         else if (*cur == '&') {
9508             xmlParseReference(ctxt);
9509         }
9510
9511         /*
9512          * Last case, text. Note that References are handled directly.
9513          */
9514         else {
9515             xmlParseCharData(ctxt, 0);
9516         }
9517
9518         GROW;
9519         /*
9520          * Pop-up of finished entities.
9521          */
9522         while ((RAW == 0) && (ctxt->inputNr > 1))
9523             xmlPopInput(ctxt);
9524         SHRINK;
9525
9526         if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
9527             xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9528                         "detected an error in element content\n");
9529             ctxt->instate = XML_PARSER_EOF;
9530             break;
9531         }
9532     }
9533 }
9534
9535 /**
9536  * xmlParseElement:
9537  * @ctxt:  an XML parser context
9538  *
9539  * parse an XML element, this is highly recursive
9540  *
9541  * [39] element ::= EmptyElemTag | STag content ETag
9542  *
9543  * [ WFC: Element Type Match ]
9544  * The Name in an element's end-tag must match the element type in the
9545  * start-tag. 
9546  *
9547  */
9548
9549 void
9550 xmlParseElement(xmlParserCtxtPtr ctxt) {
9551     const xmlChar *name;
9552     const xmlChar *prefix = NULL;
9553     const xmlChar *URI = NULL;
9554     xmlParserNodeInfo node_info;
9555     int line, tlen;
9556     xmlNodePtr ret;
9557     int nsNr = ctxt->nsNr;
9558
9559     if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
9560         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9561         xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
9562                  "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
9563                           xmlParserMaxDepth);
9564         ctxt->instate = XML_PARSER_EOF;
9565         return;
9566     }
9567
9568     /* Capture start position */
9569     if (ctxt->record_info) {
9570         node_info.begin_pos = ctxt->input->consumed +
9571                           (CUR_PTR - ctxt->input->base);
9572         node_info.begin_line = ctxt->input->line;
9573     }
9574
9575     if (ctxt->spaceNr == 0)
9576         spacePush(ctxt, -1);
9577     else if (*ctxt->space == -2)
9578         spacePush(ctxt, -1);
9579     else
9580         spacePush(ctxt, *ctxt->space);
9581
9582     line = ctxt->input->line;
9583 #ifdef LIBXML_SAX1_ENABLED
9584     if (ctxt->sax2)
9585 #endif /* LIBXML_SAX1_ENABLED */
9586         name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
9587 #ifdef LIBXML_SAX1_ENABLED
9588     else
9589         name = xmlParseStartTag(ctxt);
9590 #endif /* LIBXML_SAX1_ENABLED */
9591     if (name == NULL) {
9592         spacePop(ctxt);
9593         return;
9594     }
9595     namePush(ctxt, name);
9596     ret = ctxt->node;
9597
9598 #ifdef LIBXML_VALID_ENABLED
9599     /*
9600      * [ VC: Root Element Type ]
9601      * The Name in the document type declaration must match the element
9602      * type of the root element. 
9603      */
9604     if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
9605         ctxt->node && (ctxt->node == ctxt->myDoc->children))
9606         ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
9607 #endif /* LIBXML_VALID_ENABLED */
9608
9609     /*
9610      * Check for an Empty Element.
9611      */
9612     if ((RAW == '/') && (NXT(1) == '>')) {
9613         SKIP(2);
9614         if (ctxt->sax2) {
9615             if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9616                 (!ctxt->disableSAX))
9617                 ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
9618 #ifdef LIBXML_SAX1_ENABLED
9619         } else {
9620             if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
9621                 (!ctxt->disableSAX))
9622                 ctxt->sax->endElement(ctxt->userData, name);
9623 #endif /* LIBXML_SAX1_ENABLED */
9624         }
9625         namePop(ctxt);
9626         spacePop(ctxt);
9627         if (nsNr != ctxt->nsNr)
9628             nsPop(ctxt, ctxt->nsNr - nsNr);
9629         if ( ret != NULL && ctxt->record_info ) {
9630            node_info.end_pos = ctxt->input->consumed +
9631                               (CUR_PTR - ctxt->input->base);
9632            node_info.end_line = ctxt->input->line;
9633            node_info.node = ret;
9634            xmlParserAddNodeInfo(ctxt, &node_info);
9635         }
9636         return;
9637     }
9638     if (RAW == '>') {
9639         NEXT1;
9640     } else {
9641         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
9642                      "Couldn't find end of Start Tag %s line %d\n",
9643                                 name, line, NULL);
9644
9645         /*
9646          * end of parsing of this node.
9647          */
9648         nodePop(ctxt);
9649         namePop(ctxt);
9650         spacePop(ctxt);
9651         if (nsNr != ctxt->nsNr)
9652             nsPop(ctxt, ctxt->nsNr - nsNr);
9653
9654         /*
9655          * Capture end position and add node
9656          */
9657         if ( ret != NULL && ctxt->record_info ) {
9658            node_info.end_pos = ctxt->input->consumed +
9659                               (CUR_PTR - ctxt->input->base);
9660            node_info.end_line = ctxt->input->line;
9661            node_info.node = ret;
9662            xmlParserAddNodeInfo(ctxt, &node_info);
9663         }
9664         return;
9665     }
9666
9667     /*
9668      * Parse the content of the element:
9669      */
9670     xmlParseContent(ctxt);
9671     if (!IS_BYTE_CHAR(RAW)) {
9672         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
9673          "Premature end of data in tag %s line %d\n",
9674                                 name, line, NULL);
9675
9676         /*
9677          * end of parsing of this node.
9678          */
9679         nodePop(ctxt);
9680         namePop(ctxt);
9681         spacePop(ctxt);
9682         if (nsNr != ctxt->nsNr)
9683             nsPop(ctxt, ctxt->nsNr - nsNr);
9684         return;
9685     }
9686
9687     /*
9688      * parse the end of tag: '</' should be here.
9689      */
9690     if (ctxt->sax2) {
9691         xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
9692         namePop(ctxt);
9693     }
9694 #ifdef LIBXML_SAX1_ENABLED
9695       else
9696         xmlParseEndTag1(ctxt, line);
9697 #endif /* LIBXML_SAX1_ENABLED */
9698
9699     /*
9700      * Capture end position and add node
9701      */
9702     if ( ret != NULL && ctxt->record_info ) {
9703        node_info.end_pos = ctxt->input->consumed +
9704                           (CUR_PTR - ctxt->input->base);
9705        node_info.end_line = ctxt->input->line;
9706        node_info.node = ret;
9707        xmlParserAddNodeInfo(ctxt, &node_info);
9708     }
9709 }
9710
9711 /**
9712  * xmlParseVersionNum:
9713  * @ctxt:  an XML parser context
9714  *
9715  * parse the XML version value.
9716  *
9717  * [26] VersionNum ::= '1.' [0-9]+
9718  *
9719  * In practice allow [0-9].[0-9]+ at that level
9720  *
9721  * Returns the string giving the XML version number, or NULL
9722  */
9723 xmlChar *
9724 xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
9725     xmlChar *buf = NULL;
9726     int len = 0;
9727     int size = 10;
9728     xmlChar cur;
9729
9730     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
9731     if (buf == NULL) {
9732         xmlErrMemory(ctxt, NULL);
9733         return(NULL);
9734     }
9735     cur = CUR;
9736     if (!((cur >= '0') && (cur <= '9'))) {
9737         xmlFree(buf);
9738         return(NULL);
9739     }
9740     buf[len++] = cur;
9741     NEXT;
9742     cur=CUR;
9743     if (cur != '.') {
9744         xmlFree(buf);
9745         return(NULL);
9746     }
9747     buf[len++] = cur;
9748     NEXT;
9749     cur=CUR;
9750     while ((cur >= '0') && (cur <= '9')) {
9751         if (len + 1 >= size) {
9752             xmlChar *tmp;
9753
9754             size *= 2;
9755             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
9756             if (tmp == NULL) {
9757                 xmlFree(buf);
9758                 xmlErrMemory(ctxt, NULL);
9759                 return(NULL);
9760             }
9761             buf = tmp;
9762         }
9763         buf[len++] = cur;
9764         NEXT;
9765         cur=CUR;
9766     }
9767     buf[len] = 0;
9768     return(buf);
9769 }
9770
9771 /**
9772  * xmlParseVersionInfo:
9773  * @ctxt:  an XML parser context
9774  *
9775  * parse the XML version.
9776  *
9777  * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
9778  *
9779  * [25] Eq ::= S? '=' S?
9780  *
9781  * Returns the version string, e.g. "1.0"
9782  */
9783
9784 xmlChar *
9785 xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
9786     xmlChar *version = NULL;
9787
9788     if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
9789         SKIP(7);
9790         SKIP_BLANKS;
9791         if (RAW != '=') {
9792             xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
9793             return(NULL);
9794         }
9795         NEXT;
9796         SKIP_BLANKS;
9797         if (RAW == '"') {
9798             NEXT;
9799             version = xmlParseVersionNum(ctxt);
9800             if (RAW != '"') {
9801                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
9802             } else
9803                 NEXT;
9804         } else if (RAW == '\''){
9805             NEXT;
9806             version = xmlParseVersionNum(ctxt);
9807             if (RAW != '\'') {
9808                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
9809             } else
9810                 NEXT;
9811         } else {
9812             xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
9813         }
9814     }
9815     return(version);
9816 }
9817
9818 /**
9819  * xmlParseEncName:
9820  * @ctxt:  an XML parser context
9821  *
9822  * parse the XML encoding name
9823  *
9824  * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
9825  *
9826  * Returns the encoding name value or NULL
9827  */
9828 xmlChar *
9829 xmlParseEncName(xmlParserCtxtPtr ctxt) {
9830     xmlChar *buf = NULL;
9831     int len = 0;
9832     int size = 10;
9833     xmlChar cur;
9834
9835     cur = CUR;
9836     if (((cur >= 'a') && (cur <= 'z')) ||
9837         ((cur >= 'A') && (cur <= 'Z'))) {
9838         buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
9839         if (buf == NULL) {
9840             xmlErrMemory(ctxt, NULL);
9841             return(NULL);
9842         }
9843
9844         buf[len++] = cur;
9845         NEXT;
9846         cur = CUR;
9847         while (((cur >= 'a') && (cur <= 'z')) ||
9848                ((cur >= 'A') && (cur <= 'Z')) ||
9849                ((cur >= '0') && (cur <= '9')) ||
9850                (cur == '.') || (cur == '_') ||
9851                (cur == '-')) {
9852             if (len + 1 >= size) {
9853                 xmlChar *tmp;
9854
9855                 size *= 2;
9856                 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
9857                 if (tmp == NULL) {
9858                     xmlErrMemory(ctxt, NULL);
9859                     xmlFree(buf);
9860                     return(NULL);
9861                 }
9862                 buf = tmp;
9863             }
9864             buf[len++] = cur;
9865             NEXT;
9866             cur = CUR;
9867             if (cur == 0) {
9868                 SHRINK;
9869                 GROW;
9870                 cur = CUR;
9871             }
9872         }
9873         buf[len] = 0;
9874     } else {
9875         xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
9876     }
9877     return(buf);
9878 }
9879
9880 /**
9881  * xmlParseEncodingDecl:
9882  * @ctxt:  an XML parser context
9883  * 
9884  * parse the XML encoding declaration
9885  *
9886  * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
9887  *
9888  * this setups the conversion filters.
9889  *
9890  * Returns the encoding value or NULL
9891  */
9892
9893 const xmlChar *
9894 xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
9895     xmlChar *encoding = NULL;
9896
9897     SKIP_BLANKS;
9898     if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
9899         SKIP(8);
9900         SKIP_BLANKS;
9901         if (RAW != '=') {
9902             xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
9903             return(NULL);
9904         }
9905         NEXT;
9906         SKIP_BLANKS;
9907         if (RAW == '"') {
9908             NEXT;
9909             encoding = xmlParseEncName(ctxt);
9910             if (RAW != '"') {
9911                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
9912             } else
9913                 NEXT;
9914         } else if (RAW == '\''){
9915             NEXT;
9916             encoding = xmlParseEncName(ctxt);
9917             if (RAW != '\'') {
9918                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
9919             } else
9920                 NEXT;
9921         } else {
9922             xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
9923         }
9924         /*
9925          * UTF-16 encoding stwich has already taken place at this stage,
9926          * more over the little-endian/big-endian selection is already done
9927          */
9928         if ((encoding != NULL) &&
9929             ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
9930              (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
9931             /*
9932              * If no encoding was passed to the parser, that we are
9933              * using UTF-16 and no decoder is present i.e. the 
9934              * document is apparently UTF-8 compatible, then raise an
9935              * encoding mismatch fatal error
9936              */
9937             if ((ctxt->encoding == NULL) &&
9938                 (ctxt->input->buf != NULL) &&
9939                 (ctxt->input->buf->encoder == NULL)) {
9940                 xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
9941                   "Document labelled UTF-16 but has UTF-8 content\n");
9942             }
9943             if (ctxt->encoding != NULL)
9944                 xmlFree((xmlChar *) ctxt->encoding);
9945             ctxt->encoding = encoding;
9946         }
9947         /*
9948          * UTF-8 encoding is handled natively
9949          */
9950         else if ((encoding != NULL) &&
9951             ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
9952              (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
9953             if (ctxt->encoding != NULL)
9954                 xmlFree((xmlChar *) ctxt->encoding);
9955             ctxt->encoding = encoding;
9956         }
9957         else if (encoding != NULL) {
9958             xmlCharEncodingHandlerPtr handler;
9959
9960             if (ctxt->input->encoding != NULL)
9961                 xmlFree((xmlChar *) ctxt->input->encoding);
9962             ctxt->input->encoding = encoding;
9963
9964             handler = xmlFindCharEncodingHandler((const char *) encoding);
9965             if (handler != NULL) {
9966                 xmlSwitchToEncoding(ctxt, handler);
9967             } else {
9968                 xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
9969                         "Unsupported encoding %s\n", encoding);
9970                 return(NULL);
9971             }
9972         }
9973     }
9974     return(encoding);
9975 }
9976
9977 /**
9978  * xmlParseSDDecl:
9979  * @ctxt:  an XML parser context
9980  *
9981  * parse the XML standalone declaration
9982  *
9983  * [32] SDDecl ::= S 'standalone' Eq
9984  *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"')) 
9985  *
9986  * [ VC: Standalone Document Declaration ]
9987  * TODO The standalone document declaration must have the value "no"
9988  * if any external markup declarations contain declarations of:
9989  *  - attributes with default values, if elements to which these
9990  *    attributes apply appear in the document without specifications
9991  *    of values for these attributes, or
9992  *  - entities (other than amp, lt, gt, apos, quot), if references
9993  *    to those entities appear in the document, or
9994  *  - attributes with values subject to normalization, where the
9995  *    attribute appears in the document with a value which will change
9996  *    as a result of normalization, or
9997  *  - element types with element content, if white space occurs directly
9998  *    within any instance of those types.
9999  *
10000  * Returns:
10001  *   1 if standalone="yes"
10002  *   0 if standalone="no"
10003  *  -2 if standalone attribute is missing or invalid
10004  *        (A standalone value of -2 means that the XML declaration was found,
10005  *         but no value was specified for the standalone attribute).
10006  */
10007
10008 int
10009 xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10010     int standalone = -2;
10011
10012     SKIP_BLANKS;
10013     if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10014         SKIP(10);
10015         SKIP_BLANKS;
10016         if (RAW != '=') {
10017             xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10018             return(standalone);
10019         }
10020         NEXT;
10021         SKIP_BLANKS;
10022         if (RAW == '\''){
10023             NEXT;
10024             if ((RAW == 'n') && (NXT(1) == 'o')) {
10025                 standalone = 0;
10026                 SKIP(2);
10027             } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10028                        (NXT(2) == 's')) {
10029                 standalone = 1;
10030                 SKIP(3);
10031             } else {
10032                 xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10033             }
10034             if (RAW != '\'') {
10035                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10036             } else
10037                 NEXT;
10038         } else if (RAW == '"'){
10039             NEXT;
10040             if ((RAW == 'n') && (NXT(1) == 'o')) {
10041                 standalone = 0;
10042                 SKIP(2);
10043             } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10044                        (NXT(2) == 's')) {
10045                 standalone = 1;
10046                 SKIP(3);
10047             } else {
10048                 xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10049             }
10050             if (RAW != '"') {
10051                 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10052             } else
10053                 NEXT;
10054         } else {
10055             xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10056         }
10057     }
10058     return(standalone);
10059 }
10060
10061 /**
10062  * xmlParseXMLDecl:
10063  * @ctxt:  an XML parser context
10064  * 
10065  * parse an XML declaration header
10066  *
10067  * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10068  */
10069
10070 void
10071 xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10072     xmlChar *version;
10073
10074     /*
10075      * This value for standalone indicates that the document has an
10076      * XML declaration but it does not have a standalone attribute.
10077      * It will be overwritten later if a standalone attribute is found.
10078      */
10079     ctxt->input->standalone = -2;
10080
10081     /*
10082      * We know that '<?xml' is here.
10083      */
10084     SKIP(5);
10085
10086     if (!IS_BLANK_CH(RAW)) {
10087         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10088                        "Blank needed after '<?xml'\n");
10089     }
10090     SKIP_BLANKS;
10091
10092     /*
10093      * We must have the VersionInfo here.
10094      */
10095     version = xmlParseVersionInfo(ctxt);
10096     if (version == NULL) {
10097         xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10098     } else {
10099         if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10100             /*
10101              * Changed here for XML-1.0 5th edition
10102              */
10103             if (ctxt->options & XML_PARSE_OLD10) {
10104                 xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10105                                   "Unsupported version '%s'\n",
10106                                   version);
10107             } else {
10108                 if ((version[0] == '1') && ((version[1] == '.'))) {
10109                     xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10110                                   "Unsupported version '%s'\n",
10111                                   version, NULL);
10112                 } else {
10113                     xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10114                                       "Unsupported version '%s'\n",
10115                                       version);
10116                 }
10117             }
10118         }
10119         if (ctxt->version != NULL)
10120             xmlFree((void *) ctxt->version);
10121         ctxt->version = version;
10122     }
10123
10124     /*
10125      * We may have the encoding declaration
10126      */
10127     if (!IS_BLANK_CH(RAW)) {
10128         if ((RAW == '?') && (NXT(1) == '>')) {
10129             SKIP(2);
10130             return;
10131         }
10132         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10133     }
10134     xmlParseEncodingDecl(ctxt);
10135     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10136         /*
10137          * The XML REC instructs us to stop parsing right here
10138          */
10139         return;
10140     }
10141
10142     /*
10143      * We may have the standalone status.
10144      */
10145     if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10146         if ((RAW == '?') && (NXT(1) == '>')) {
10147             SKIP(2);
10148             return;
10149         }
10150         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10151     }
10152
10153     /*
10154      * We can grow the input buffer freely at that point
10155      */
10156     GROW;
10157
10158     SKIP_BLANKS;
10159     ctxt->input->standalone = xmlParseSDDecl(ctxt);
10160
10161     SKIP_BLANKS;
10162     if ((RAW == '?') && (NXT(1) == '>')) {
10163         SKIP(2);
10164     } else if (RAW == '>') {
10165         /* Deprecated old WD ... */
10166         xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10167         NEXT;
10168     } else {
10169         xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10170         MOVETO_ENDTAG(CUR_PTR);
10171         NEXT;
10172     }
10173 }
10174
10175 /**
10176  * xmlParseMisc:
10177  * @ctxt:  an XML parser context
10178  * 
10179  * parse an XML Misc* optional field.
10180  *
10181  * [27] Misc ::= Comment | PI |  S
10182  */
10183
10184 void
10185 xmlParseMisc(xmlParserCtxtPtr ctxt) {
10186     while (((RAW == '<') && (NXT(1) == '?')) ||
10187            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
10188            IS_BLANK_CH(CUR)) {
10189         if ((RAW == '<') && (NXT(1) == '?')) {
10190             xmlParsePI(ctxt);
10191         } else if (IS_BLANK_CH(CUR)) {
10192             NEXT;
10193         } else
10194             xmlParseComment(ctxt);
10195     }
10196 }
10197
10198 /**
10199  * xmlParseDocument:
10200  * @ctxt:  an XML parser context
10201  * 
10202  * parse an XML document (and build a tree if using the standard SAX
10203  * interface).
10204  *
10205  * [1] document ::= prolog element Misc*
10206  *
10207  * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10208  *
10209  * Returns 0, -1 in case of error. the parser context is augmented
10210  *                as a result of the parsing.
10211  */
10212
10213 int
10214 xmlParseDocument(xmlParserCtxtPtr ctxt) {
10215     xmlChar start[4];
10216     xmlCharEncoding enc;
10217
10218     xmlInitParser();
10219
10220     if ((ctxt == NULL) || (ctxt->input == NULL))
10221         return(-1);
10222
10223     GROW;
10224
10225     /*
10226      * SAX: detecting the level.
10227      */
10228     xmlDetectSAX2(ctxt);
10229
10230     /*
10231      * SAX: beginning of the document processing.
10232      */
10233     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10234         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10235
10236     if ((ctxt->encoding == NULL) &&
10237         ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10238         /* 
10239          * Get the 4 first bytes and decode the charset
10240          * if enc != XML_CHAR_ENCODING_NONE
10241          * plug some encoding conversion routines.
10242          */
10243         start[0] = RAW;
10244         start[1] = NXT(1);
10245         start[2] = NXT(2);
10246         start[3] = NXT(3);
10247         enc = xmlDetectCharEncoding(&start[0], 4);
10248         if (enc != XML_CHAR_ENCODING_NONE) {
10249             xmlSwitchEncoding(ctxt, enc);
10250         }
10251     }
10252
10253
10254     if (CUR == 0) {
10255         xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10256     }
10257
10258     /*
10259      * Check for the XMLDecl in the Prolog.
10260      * do not GROW here to avoid the detected encoder to decode more
10261      * than just the first line, unless the amount of data is really
10262      * too small to hold "<?xml version="1.0" encoding="foo"
10263      */
10264     if ((ctxt->input->end - ctxt->input->cur) < 35) {
10265        GROW;
10266     }
10267     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10268
10269         /*
10270          * Note that we will switch encoding on the fly.
10271          */
10272         xmlParseXMLDecl(ctxt);
10273         if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10274             /*
10275              * The XML REC instructs us to stop parsing right here
10276              */
10277             return(-1);
10278         }
10279         ctxt->standalone = ctxt->input->standalone;
10280         SKIP_BLANKS;
10281     } else {
10282         ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10283     }
10284     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10285         ctxt->sax->startDocument(ctxt->userData);
10286
10287     /*
10288      * The Misc part of the Prolog
10289      */
10290     GROW;
10291     xmlParseMisc(ctxt);
10292
10293     /*
10294      * Then possibly doc type declaration(s) and more Misc
10295      * (doctypedecl Misc*)?
10296      */
10297     GROW;
10298     if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10299
10300         ctxt->inSubset = 1;
10301         xmlParseDocTypeDecl(ctxt);
10302         if (RAW == '[') {
10303             ctxt->instate = XML_PARSER_DTD;
10304             xmlParseInternalSubset(ctxt);
10305         }
10306
10307         /*
10308          * Create and update the external subset.
10309          */
10310         ctxt->inSubset = 2;
10311         if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10312             (!ctxt->disableSAX))
10313             ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10314                                       ctxt->extSubSystem, ctxt->extSubURI);
10315         ctxt->inSubset = 0;
10316
10317         xmlCleanSpecialAttr(ctxt);
10318
10319         ctxt->instate = XML_PARSER_PROLOG;
10320         xmlParseMisc(ctxt);
10321     }
10322
10323     /*
10324      * Time to start parsing the tree itself
10325      */
10326     GROW;
10327     if (RAW != '<') {
10328         xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10329                        "Start tag expected, '<' not found\n");
10330     } else {
10331         ctxt->instate = XML_PARSER_CONTENT;
10332         xmlParseElement(ctxt);
10333         ctxt->instate = XML_PARSER_EPILOG;
10334
10335
10336         /*
10337          * The Misc part at the end
10338          */
10339         xmlParseMisc(ctxt);
10340
10341         if (RAW != 0) {
10342             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10343         }
10344         ctxt->instate = XML_PARSER_EOF;
10345     }
10346
10347     /*
10348      * SAX: end of the document processing.
10349      */
10350     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10351         ctxt->sax->endDocument(ctxt->userData);
10352
10353     /*
10354      * Remove locally kept entity definitions if the tree was not built
10355      */
10356     if ((ctxt->myDoc != NULL) &&
10357         (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10358         xmlFreeDoc(ctxt->myDoc);
10359         ctxt->myDoc = NULL;
10360     }
10361
10362     if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10363         ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10364         if (ctxt->valid)
10365             ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10366         if (ctxt->nsWellFormed)
10367             ctxt->myDoc->properties |= XML_DOC_NSVALID;
10368         if (ctxt->options & XML_PARSE_OLD10)
10369             ctxt->myDoc->properties |= XML_DOC_OLD10;
10370     }
10371     if (! ctxt->wellFormed) {
10372         ctxt->valid = 0;
10373         return(-1);
10374     }
10375     return(0);
10376 }
10377
10378 /**
10379  * xmlParseExtParsedEnt:
10380  * @ctxt:  an XML parser context
10381  * 
10382  * parse a general parsed entity
10383  * An external general parsed entity is well-formed if it matches the
10384  * production labeled extParsedEnt.
10385  *
10386  * [78] extParsedEnt ::= TextDecl? content
10387  *
10388  * Returns 0, -1 in case of error. the parser context is augmented
10389  *                as a result of the parsing.
10390  */
10391
10392 int
10393 xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10394     xmlChar start[4];
10395     xmlCharEncoding enc;
10396
10397     if ((ctxt == NULL) || (ctxt->input == NULL))
10398         return(-1);
10399
10400     xmlDefaultSAXHandlerInit();
10401
10402     xmlDetectSAX2(ctxt);
10403
10404     GROW;
10405
10406     /*
10407      * SAX: beginning of the document processing.
10408      */
10409     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10410         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10411
10412     /* 
10413      * Get the 4 first bytes and decode the charset
10414      * if enc != XML_CHAR_ENCODING_NONE
10415      * plug some encoding conversion routines.
10416      */
10417     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
10418         start[0] = RAW;
10419         start[1] = NXT(1);
10420         start[2] = NXT(2);
10421         start[3] = NXT(3);
10422         enc = xmlDetectCharEncoding(start, 4);
10423         if (enc != XML_CHAR_ENCODING_NONE) {
10424             xmlSwitchEncoding(ctxt, enc);
10425         }
10426     }
10427
10428
10429     if (CUR == 0) {
10430         xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10431     }
10432
10433     /*
10434      * Check for the XMLDecl in the Prolog.
10435      */
10436     GROW;
10437     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10438
10439         /*
10440          * Note that we will switch encoding on the fly.
10441          */
10442         xmlParseXMLDecl(ctxt);
10443         if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10444             /*
10445              * The XML REC instructs us to stop parsing right here
10446              */
10447             return(-1);
10448         }
10449         SKIP_BLANKS;
10450     } else {
10451         ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10452     }
10453     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10454         ctxt->sax->startDocument(ctxt->userData);
10455
10456     /*
10457      * Doing validity checking on chunk doesn't make sense
10458      */
10459     ctxt->instate = XML_PARSER_CONTENT;
10460     ctxt->validate = 0;
10461     ctxt->loadsubset = 0;
10462     ctxt->depth = 0;
10463
10464     xmlParseContent(ctxt);
10465    
10466     if ((RAW == '<') && (NXT(1) == '/')) {
10467         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
10468     } else if (RAW != 0) {
10469         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
10470     }
10471
10472     /*
10473      * SAX: end of the document processing.
10474      */
10475     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10476         ctxt->sax->endDocument(ctxt->userData);
10477
10478     if (! ctxt->wellFormed) return(-1);
10479     return(0);
10480 }
10481
10482 #ifdef LIBXML_PUSH_ENABLED
10483 /************************************************************************
10484  *                                                                      *
10485  *              Progressive parsing interfaces                          *
10486  *                                                                      *
10487  ************************************************************************/
10488
10489 /**
10490  * xmlParseLookupSequence:
10491  * @ctxt:  an XML parser context
10492  * @first:  the first char to lookup
10493  * @next:  the next char to lookup or zero
10494  * @third:  the next char to lookup or zero
10495  *
10496  * Try to find if a sequence (first, next, third) or  just (first next) or
10497  * (first) is available in the input stream.
10498  * This function has a side effect of (possibly) incrementing ctxt->checkIndex
10499  * to avoid rescanning sequences of bytes, it DOES change the state of the
10500  * parser, do not use liberally.
10501  *
10502  * Returns the index to the current parsing point if the full sequence
10503  *      is available, -1 otherwise.
10504  */
10505 static int
10506 xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
10507                        xmlChar next, xmlChar third) {
10508     int base, len;
10509     xmlParserInputPtr in;
10510     const xmlChar *buf;
10511
10512     in = ctxt->input;
10513     if (in == NULL) return(-1);
10514     base = in->cur - in->base;
10515     if (base < 0) return(-1);
10516     if (ctxt->checkIndex > base)
10517         base = ctxt->checkIndex;
10518     if (in->buf == NULL) {
10519         buf = in->base;
10520         len = in->length;
10521     } else {
10522         buf = in->buf->buffer->content;
10523         len = in->buf->buffer->use;
10524     }
10525     /* take into account the sequence length */
10526     if (third) len -= 2;
10527     else if (next) len --;
10528     for (;base < len;base++) {
10529         if (buf[base] == first) {
10530             if (third != 0) {
10531                 if ((buf[base + 1] != next) ||
10532                     (buf[base + 2] != third)) continue;
10533             } else if (next != 0) {
10534                 if (buf[base + 1] != next) continue;
10535             }
10536             ctxt->checkIndex = 0;
10537 #ifdef DEBUG_PUSH
10538             if (next == 0)
10539                 xmlGenericError(xmlGenericErrorContext,
10540                         "PP: lookup '%c' found at %d\n",
10541                         first, base);
10542             else if (third == 0)
10543                 xmlGenericError(xmlGenericErrorContext,
10544                         "PP: lookup '%c%c' found at %d\n",
10545                         first, next, base);
10546             else 
10547                 xmlGenericError(xmlGenericErrorContext,
10548                         "PP: lookup '%c%c%c' found at %d\n",
10549                         first, next, third, base);
10550 #endif
10551             return(base - (in->cur - in->base));
10552         }
10553     }
10554     ctxt->checkIndex = base;
10555 #ifdef DEBUG_PUSH
10556     if (next == 0)
10557         xmlGenericError(xmlGenericErrorContext,
10558                 "PP: lookup '%c' failed\n", first);
10559     else if (third == 0)
10560         xmlGenericError(xmlGenericErrorContext,
10561                 "PP: lookup '%c%c' failed\n", first, next);
10562     else        
10563         xmlGenericError(xmlGenericErrorContext,
10564                 "PP: lookup '%c%c%c' failed\n", first, next, third);
10565 #endif
10566     return(-1);
10567 }
10568
10569 /**
10570  * xmlParseGetLasts:
10571  * @ctxt:  an XML parser context
10572  * @lastlt:  pointer to store the last '<' from the input
10573  * @lastgt:  pointer to store the last '>' from the input
10574  *
10575  * Lookup the last < and > in the current chunk
10576  */
10577 static void
10578 xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
10579                  const xmlChar **lastgt) {
10580     const xmlChar *tmp;
10581
10582     if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
10583         xmlGenericError(xmlGenericErrorContext,
10584                     "Internal error: xmlParseGetLasts\n");
10585         return;
10586     }
10587     if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
10588         tmp = ctxt->input->end;
10589         tmp--;
10590         while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
10591         if (tmp < ctxt->input->base) {
10592             *lastlt = NULL;
10593             *lastgt = NULL;
10594         } else {
10595             *lastlt = tmp;
10596             tmp++;
10597             while ((tmp < ctxt->input->end) && (*tmp != '>')) {
10598                 if (*tmp == '\'') {
10599                     tmp++;
10600                     while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
10601                     if (tmp < ctxt->input->end) tmp++;
10602                 } else if (*tmp == '"') {
10603                     tmp++;
10604                     while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
10605                     if (tmp < ctxt->input->end) tmp++;
10606                 } else
10607                     tmp++;
10608             }
10609             if (tmp < ctxt->input->end)
10610                 *lastgt = tmp;
10611             else {
10612                 tmp = *lastlt;
10613                 tmp--;
10614                 while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
10615                 if (tmp >= ctxt->input->base)
10616                     *lastgt = tmp;
10617                 else
10618                     *lastgt = NULL;
10619             }
10620         }
10621     } else {
10622         *lastlt = NULL;
10623         *lastgt = NULL;
10624     }
10625 }
10626 /**
10627  * xmlCheckCdataPush:
10628  * @cur: pointer to the bock of characters
10629  * @len: length of the block in bytes
10630  *
10631  * Check that the block of characters is okay as SCdata content [20]
10632  *
10633  * Returns the number of bytes to pass if okay, a negative index where an
10634  *         UTF-8 error occured otherwise
10635  */
10636 static int
10637 xmlCheckCdataPush(const xmlChar *utf, int len) {
10638     int ix;
10639     unsigned char c;
10640     int codepoint;
10641
10642     if ((utf == NULL) || (len <= 0))
10643         return(0);
10644     
10645     for (ix = 0; ix < len;) {      /* string is 0-terminated */
10646         c = utf[ix];
10647         if ((c & 0x80) == 0x00) {       /* 1-byte code, starts with 10 */
10648             if (c >= 0x20)
10649                 ix++;
10650             else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
10651                 ix++;
10652             else
10653                 return(-ix);
10654         } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
10655             if (ix + 2 > len) return(ix);
10656             if ((utf[ix+1] & 0xc0 ) != 0x80)
10657                 return(-ix);
10658             codepoint = (utf[ix] & 0x1f) << 6;
10659             codepoint |= utf[ix+1] & 0x3f;
10660             if (!xmlIsCharQ(codepoint))
10661                 return(-ix);
10662             ix += 2;
10663         } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
10664             if (ix + 3 > len) return(ix);
10665             if (((utf[ix+1] & 0xc0) != 0x80) ||
10666                 ((utf[ix+2] & 0xc0) != 0x80))
10667                     return(-ix);
10668             codepoint = (utf[ix] & 0xf) << 12;
10669             codepoint |= (utf[ix+1] & 0x3f) << 6;
10670             codepoint |= utf[ix+2] & 0x3f;
10671             if (!xmlIsCharQ(codepoint))
10672                 return(-ix);
10673             ix += 3;
10674         } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
10675             if (ix + 4 > len) return(ix);
10676             if (((utf[ix+1] & 0xc0) != 0x80) ||
10677                 ((utf[ix+2] & 0xc0) != 0x80) ||
10678                 ((utf[ix+3] & 0xc0) != 0x80))
10679                     return(-ix);
10680             codepoint = (utf[ix] & 0x7) << 18;
10681             codepoint |= (utf[ix+1] & 0x3f) << 12;
10682             codepoint |= (utf[ix+2] & 0x3f) << 6;
10683             codepoint |= utf[ix+3] & 0x3f;
10684             if (!xmlIsCharQ(codepoint))
10685                 return(-ix);
10686             ix += 4;
10687         } else                          /* unknown encoding */
10688             return(-ix);
10689       }
10690       return(ix);
10691 }
10692
10693 /**
10694  * xmlParseTryOrFinish:
10695  * @ctxt:  an XML parser context
10696  * @terminate:  last chunk indicator
10697  *
10698  * Try to progress on parsing
10699  *
10700  * Returns zero if no parsing was possible
10701  */
10702 static int
10703 xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
10704     int ret = 0;
10705     int avail, tlen;
10706     xmlChar cur, next;
10707     const xmlChar *lastlt, *lastgt;
10708
10709     if (ctxt->input == NULL)
10710         return(0);
10711
10712 #ifdef DEBUG_PUSH
10713     switch (ctxt->instate) {
10714         case XML_PARSER_EOF:
10715             xmlGenericError(xmlGenericErrorContext,
10716                     "PP: try EOF\n"); break;
10717         case XML_PARSER_START:
10718             xmlGenericError(xmlGenericErrorContext,
10719                     "PP: try START\n"); break;
10720         case XML_PARSER_MISC:
10721             xmlGenericError(xmlGenericErrorContext,
10722                     "PP: try MISC\n");break;
10723         case XML_PARSER_COMMENT:
10724             xmlGenericError(xmlGenericErrorContext,
10725                     "PP: try COMMENT\n");break;
10726         case XML_PARSER_PROLOG:
10727             xmlGenericError(xmlGenericErrorContext,
10728                     "PP: try PROLOG\n");break;
10729         case XML_PARSER_START_TAG:
10730             xmlGenericError(xmlGenericErrorContext,
10731                     "PP: try START_TAG\n");break;
10732         case XML_PARSER_CONTENT:
10733             xmlGenericError(xmlGenericErrorContext,
10734                     "PP: try CONTENT\n");break;
10735         case XML_PARSER_CDATA_SECTION:
10736             xmlGenericError(xmlGenericErrorContext,
10737                     "PP: try CDATA_SECTION\n");break;
10738         case XML_PARSER_END_TAG:
10739             xmlGenericError(xmlGenericErrorContext,
10740                     "PP: try END_TAG\n");break;
10741         case XML_PARSER_ENTITY_DECL:
10742             xmlGenericError(xmlGenericErrorContext,
10743                     "PP: try ENTITY_DECL\n");break;
10744         case XML_PARSER_ENTITY_VALUE:
10745             xmlGenericError(xmlGenericErrorContext,
10746                     "PP: try ENTITY_VALUE\n");break;
10747         case XML_PARSER_ATTRIBUTE_VALUE:
10748             xmlGenericError(xmlGenericErrorContext,
10749                     "PP: try ATTRIBUTE_VALUE\n");break;
10750         case XML_PARSER_DTD:
10751             xmlGenericError(xmlGenericErrorContext,
10752                     "PP: try DTD\n");break;
10753         case XML_PARSER_EPILOG:
10754             xmlGenericError(xmlGenericErrorContext,
10755                     "PP: try EPILOG\n");break;
10756         case XML_PARSER_PI:
10757             xmlGenericError(xmlGenericErrorContext,
10758                     "PP: try PI\n");break;
10759         case XML_PARSER_IGNORE:
10760             xmlGenericError(xmlGenericErrorContext,
10761                     "PP: try IGNORE\n");break;
10762     }
10763 #endif
10764
10765     if ((ctxt->input != NULL) &&
10766         (ctxt->input->cur - ctxt->input->base > 4096)) {
10767         xmlSHRINK(ctxt);
10768         ctxt->checkIndex = 0;
10769     }
10770     xmlParseGetLasts(ctxt, &lastlt, &lastgt);
10771
10772     while (1) {
10773         if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
10774             return(0);
10775
10776         
10777         /*
10778          * Pop-up of finished entities.
10779          */
10780         while ((RAW == 0) && (ctxt->inputNr > 1))
10781             xmlPopInput(ctxt);
10782
10783         if (ctxt->input == NULL) break;
10784         if (ctxt->input->buf == NULL)
10785             avail = ctxt->input->length -
10786                     (ctxt->input->cur - ctxt->input->base);
10787         else {
10788             /*
10789              * If we are operating on converted input, try to flush
10790              * remainng chars to avoid them stalling in the non-converted
10791              * buffer.
10792              */
10793             if ((ctxt->input->buf->raw != NULL) &&
10794                 (ctxt->input->buf->raw->use > 0)) {
10795                 int base = ctxt->input->base -
10796                            ctxt->input->buf->buffer->content;
10797                 int current = ctxt->input->cur - ctxt->input->base;
10798
10799                 xmlParserInputBufferPush(ctxt->input->buf, 0, "");
10800                 ctxt->input->base = ctxt->input->buf->buffer->content + base;
10801                 ctxt->input->cur = ctxt->input->base + current;
10802                 ctxt->input->end =
10803                     &ctxt->input->buf->buffer->content[
10804                                        ctxt->input->buf->buffer->use];
10805             }
10806             avail = ctxt->input->buf->buffer->use -
10807                     (ctxt->input->cur - ctxt->input->base);
10808         }
10809         if (avail < 1)
10810             goto done;
10811         switch (ctxt->instate) {
10812             case XML_PARSER_EOF:
10813                 /*
10814                  * Document parsing is done !
10815                  */
10816                 goto done;
10817             case XML_PARSER_START:
10818                 if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
10819                     xmlChar start[4];
10820                     xmlCharEncoding enc;
10821
10822                     /*
10823                      * Very first chars read from the document flow.
10824                      */
10825                     if (avail < 4)
10826                         goto done;
10827
10828                     /* 
10829                      * Get the 4 first bytes and decode the charset
10830                      * if enc != XML_CHAR_ENCODING_NONE
10831                      * plug some encoding conversion routines,
10832                      * else xmlSwitchEncoding will set to (default)
10833                      * UTF8.
10834                      */
10835                     start[0] = RAW;
10836                     start[1] = NXT(1);
10837                     start[2] = NXT(2);
10838                     start[3] = NXT(3);
10839                     enc = xmlDetectCharEncoding(start, 4);
10840                     xmlSwitchEncoding(ctxt, enc);
10841                     break;
10842                 }
10843
10844                 if (avail < 2)
10845                     goto done;
10846                 cur = ctxt->input->cur[0];
10847                 next = ctxt->input->cur[1];
10848                 if (cur == 0) {
10849                     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10850                         ctxt->sax->setDocumentLocator(ctxt->userData,
10851                                                       &xmlDefaultSAXLocator);
10852                     xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10853                     ctxt->instate = XML_PARSER_EOF;
10854 #ifdef DEBUG_PUSH
10855                     xmlGenericError(xmlGenericErrorContext,
10856                             "PP: entering EOF\n");
10857 #endif
10858                     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10859                         ctxt->sax->endDocument(ctxt->userData);
10860                     goto done;
10861                 }
10862                 if ((cur == '<') && (next == '?')) {
10863                     /* PI or XML decl */
10864                     if (avail < 5) return(ret);
10865                     if ((!terminate) &&
10866                         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
10867                         return(ret);
10868                     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10869                         ctxt->sax->setDocumentLocator(ctxt->userData,
10870                                                       &xmlDefaultSAXLocator);
10871                     if ((ctxt->input->cur[2] == 'x') &&
10872                         (ctxt->input->cur[3] == 'm') &&
10873                         (ctxt->input->cur[4] == 'l') &&
10874                         (IS_BLANK_CH(ctxt->input->cur[5]))) {
10875                         ret += 5;
10876 #ifdef DEBUG_PUSH
10877                         xmlGenericError(xmlGenericErrorContext,
10878                                 "PP: Parsing XML Decl\n");
10879 #endif
10880                         xmlParseXMLDecl(ctxt);
10881                         if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10882                             /*
10883                              * The XML REC instructs us to stop parsing right
10884                              * here
10885                              */
10886                             ctxt->instate = XML_PARSER_EOF;
10887                             return(0);
10888                         }
10889                         ctxt->standalone = ctxt->input->standalone;
10890                         if ((ctxt->encoding == NULL) &&
10891                             (ctxt->input->encoding != NULL))
10892                             ctxt->encoding = xmlStrdup(ctxt->input->encoding);
10893                         if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10894                             (!ctxt->disableSAX))
10895                             ctxt->sax->startDocument(ctxt->userData);
10896                         ctxt->instate = XML_PARSER_MISC;
10897 #ifdef DEBUG_PUSH
10898                         xmlGenericError(xmlGenericErrorContext,
10899                                 "PP: entering MISC\n");
10900 #endif
10901                     } else {
10902                         ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10903                         if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10904                             (!ctxt->disableSAX))
10905                             ctxt->sax->startDocument(ctxt->userData);
10906                         ctxt->instate = XML_PARSER_MISC;
10907 #ifdef DEBUG_PUSH
10908                         xmlGenericError(xmlGenericErrorContext,
10909                                 "PP: entering MISC\n");
10910 #endif
10911                     }
10912                 } else {
10913                     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10914                         ctxt->sax->setDocumentLocator(ctxt->userData,
10915                                                       &xmlDefaultSAXLocator);
10916                     ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10917                     if (ctxt->version == NULL) {
10918                         xmlErrMemory(ctxt, NULL);
10919                         break;
10920                     }
10921                     if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10922                         (!ctxt->disableSAX))
10923                         ctxt->sax->startDocument(ctxt->userData);
10924                     ctxt->instate = XML_PARSER_MISC;
10925 #ifdef DEBUG_PUSH
10926                     xmlGenericError(xmlGenericErrorContext,
10927                             "PP: entering MISC\n");
10928 #endif
10929                 }
10930                 break;
10931             case XML_PARSER_START_TAG: {
10932                 const xmlChar *name;
10933                 const xmlChar *prefix = NULL;
10934                 const xmlChar *URI = NULL;
10935                 int nsNr = ctxt->nsNr;
10936
10937                 if ((avail < 2) && (ctxt->inputNr == 1))
10938                     goto done;
10939                 cur = ctxt->input->cur[0];
10940                 if (cur != '<') {
10941                     xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10942                     ctxt->instate = XML_PARSER_EOF;
10943                     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10944                         ctxt->sax->endDocument(ctxt->userData);
10945                     goto done;
10946                 }
10947                 if (!terminate) {
10948                     if (ctxt->progressive) {
10949                         /* > can be found unescaped in attribute values */
10950                         if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
10951                             goto done;
10952                     } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
10953                         goto done;
10954                     }
10955                 }
10956                 if (ctxt->spaceNr == 0)
10957                     spacePush(ctxt, -1);
10958                 else if (*ctxt->space == -2)
10959                     spacePush(ctxt, -1);
10960                 else
10961                     spacePush(ctxt, *ctxt->space);
10962 #ifdef LIBXML_SAX1_ENABLED
10963                 if (ctxt->sax2)
10964 #endif /* LIBXML_SAX1_ENABLED */
10965                     name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10966 #ifdef LIBXML_SAX1_ENABLED
10967                 else
10968                     name = xmlParseStartTag(ctxt);
10969 #endif /* LIBXML_SAX1_ENABLED */
10970                 if (name == NULL) {
10971                     spacePop(ctxt);
10972                     ctxt->instate = XML_PARSER_EOF;
10973                     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10974                         ctxt->sax->endDocument(ctxt->userData);
10975                     goto done;
10976                 }
10977 #ifdef LIBXML_VALID_ENABLED
10978                 /*
10979                  * [ VC: Root Element Type ]
10980                  * The Name in the document type declaration must match
10981                  * the element type of the root element. 
10982                  */
10983                 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10984                     ctxt->node && (ctxt->node == ctxt->myDoc->children))
10985                     ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10986 #endif /* LIBXML_VALID_ENABLED */
10987
10988                 /*
10989                  * Check for an Empty Element.
10990                  */
10991                 if ((RAW == '/') && (NXT(1) == '>')) {
10992                     SKIP(2);
10993
10994                     if (ctxt->sax2) {
10995                         if ((ctxt->sax != NULL) &&
10996                             (ctxt->sax->endElementNs != NULL) &&
10997                             (!ctxt->disableSAX))
10998                             ctxt->sax->endElementNs(ctxt->userData, name,
10999                                                     prefix, URI);
11000                         if (ctxt->nsNr - nsNr > 0)
11001                             nsPop(ctxt, ctxt->nsNr - nsNr);
11002 #ifdef LIBXML_SAX1_ENABLED
11003                     } else {
11004                         if ((ctxt->sax != NULL) &&
11005                             (ctxt->sax->endElement != NULL) &&
11006                             (!ctxt->disableSAX))
11007                             ctxt->sax->endElement(ctxt->userData, name);
11008 #endif /* LIBXML_SAX1_ENABLED */
11009                     }
11010                     spacePop(ctxt);
11011                     if (ctxt->nameNr == 0) {
11012                         ctxt->instate = XML_PARSER_EPILOG;
11013                     } else {
11014                         ctxt->instate = XML_PARSER_CONTENT;
11015                     }
11016                     break;
11017                 }
11018                 if (RAW == '>') {
11019                     NEXT;
11020                 } else {
11021                     xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11022                                          "Couldn't find end of Start Tag %s\n",
11023                                          name);
11024                     nodePop(ctxt);
11025                     spacePop(ctxt);
11026                 }
11027                 if (ctxt->sax2)
11028                     nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
11029 #ifdef LIBXML_SAX1_ENABLED
11030                 else
11031                     namePush(ctxt, name);
11032 #endif /* LIBXML_SAX1_ENABLED */
11033
11034                 ctxt->instate = XML_PARSER_CONTENT;
11035                 break;
11036             }
11037             case XML_PARSER_CONTENT: {
11038                 const xmlChar *test;
11039                 unsigned int cons;
11040                 if ((avail < 2) && (ctxt->inputNr == 1))
11041                     goto done;
11042                 cur = ctxt->input->cur[0];
11043                 next = ctxt->input->cur[1];
11044
11045                 test = CUR_PTR;
11046                 cons = ctxt->input->consumed;
11047                 if ((cur == '<') && (next == '/')) {
11048                     ctxt->instate = XML_PARSER_END_TAG;
11049                     break;
11050                 } else if ((cur == '<') && (next == '?')) {
11051                     if ((!terminate) &&
11052                         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11053                         goto done;
11054                     xmlParsePI(ctxt);
11055                 } else if ((cur == '<') && (next != '!')) {
11056                     ctxt->instate = XML_PARSER_START_TAG;
11057                     break;
11058                 } else if ((cur == '<') && (next == '!') &&
11059                            (ctxt->input->cur[2] == '-') &&
11060                            (ctxt->input->cur[3] == '-')) {
11061                     int term;
11062
11063                     if (avail < 4)
11064                         goto done;
11065                     ctxt->input->cur += 4;
11066                     term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11067                     ctxt->input->cur -= 4;
11068                     if ((!terminate) && (term < 0))
11069                         goto done;
11070                     xmlParseComment(ctxt);
11071                     ctxt->instate = XML_PARSER_CONTENT;
11072                 } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11073                     (ctxt->input->cur[2] == '[') &&
11074                     (ctxt->input->cur[3] == 'C') &&
11075                     (ctxt->input->cur[4] == 'D') &&
11076                     (ctxt->input->cur[5] == 'A') &&
11077                     (ctxt->input->cur[6] == 'T') &&
11078                     (ctxt->input->cur[7] == 'A') &&
11079                     (ctxt->input->cur[8] == '[')) {
11080                     SKIP(9);
11081                     ctxt->instate = XML_PARSER_CDATA_SECTION;
11082                     break;
11083                 } else if ((cur == '<') && (next == '!') &&
11084                            (avail < 9)) {
11085                     goto done;
11086                 } else if (cur == '&') {
11087                     if ((!terminate) &&
11088                         (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11089                         goto done;
11090                     xmlParseReference(ctxt);
11091                 } else {
11092                     /* TODO Avoid the extra copy, handle directly !!! */
11093                     /*
11094                      * Goal of the following test is:
11095                      *  - minimize calls to the SAX 'character' callback
11096                      *    when they are mergeable
11097                      *  - handle an problem for isBlank when we only parse
11098                      *    a sequence of blank chars and the next one is
11099                      *    not available to check against '<' presence.
11100                      *  - tries to homogenize the differences in SAX
11101                      *    callbacks between the push and pull versions
11102                      *    of the parser.
11103                      */
11104                     if ((ctxt->inputNr == 1) &&
11105                         (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11106                         if (!terminate) {
11107                             if (ctxt->progressive) {
11108                                 if ((lastlt == NULL) ||
11109                                     (ctxt->input->cur > lastlt))
11110                                     goto done;
11111                             } else if (xmlParseLookupSequence(ctxt,
11112                                                               '<', 0, 0) < 0) {
11113                                 goto done;
11114                             }
11115                         }
11116                     }
11117                     ctxt->checkIndex = 0;
11118                     xmlParseCharData(ctxt, 0);
11119                 }
11120                 /*
11121                  * Pop-up of finished entities.
11122                  */
11123                 while ((RAW == 0) && (ctxt->inputNr > 1))
11124                     xmlPopInput(ctxt);
11125                 if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
11126                     xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11127                                 "detected an error in element content\n");
11128                     ctxt->instate = XML_PARSER_EOF;
11129                     break;
11130                 }
11131                 break;
11132             }
11133             case XML_PARSER_END_TAG:
11134                 if (avail < 2)
11135                     goto done;
11136                 if (!terminate) {
11137                     if (ctxt->progressive) {
11138                         /* > can be found unescaped in attribute values */
11139                         if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11140                             goto done;
11141                     } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11142                         goto done;
11143                     }
11144                 }
11145                 if (ctxt->sax2) {
11146                     xmlParseEndTag2(ctxt,
11147                            (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
11148                            (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
11149                        (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
11150                     nameNsPop(ctxt);
11151                 }
11152 #ifdef LIBXML_SAX1_ENABLED
11153                   else
11154                     xmlParseEndTag1(ctxt, 0);
11155 #endif /* LIBXML_SAX1_ENABLED */
11156                 if (ctxt->nameNr == 0) {
11157                     ctxt->instate = XML_PARSER_EPILOG;
11158                 } else {
11159                     ctxt->instate = XML_PARSER_CONTENT;
11160                 }
11161                 break;
11162             case XML_PARSER_CDATA_SECTION: {
11163                 /*
11164                  * The Push mode need to have the SAX callback for 
11165                  * cdataBlock merge back contiguous callbacks.
11166                  */
11167                 int base;
11168
11169                 base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11170                 if (base < 0) {
11171                     if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11172                         int tmp;
11173
11174                         tmp = xmlCheckCdataPush(ctxt->input->cur, 
11175                                                 XML_PARSER_BIG_BUFFER_SIZE);
11176                         if (tmp < 0) {
11177                             tmp = -tmp;
11178                             ctxt->input->cur += tmp;
11179                             goto encoding_error;
11180                         }
11181                         if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11182                             if (ctxt->sax->cdataBlock != NULL)
11183                                 ctxt->sax->cdataBlock(ctxt->userData,
11184                                                       ctxt->input->cur, tmp);
11185                             else if (ctxt->sax->characters != NULL)
11186                                 ctxt->sax->characters(ctxt->userData,
11187                                                       ctxt->input->cur, tmp);
11188                         }
11189                         SKIPL(tmp);
11190                         ctxt->checkIndex = 0;
11191                     }
11192                     goto done;
11193                 } else {
11194                     int tmp;
11195
11196                     tmp = xmlCheckCdataPush(ctxt->input->cur, base);
11197                     if ((tmp < 0) || (tmp != base)) {
11198                         tmp = -tmp;
11199                         ctxt->input->cur += tmp;
11200                         goto encoding_error;
11201                     }
11202                     if ((ctxt->sax != NULL) && (base == 0) &&
11203                         (ctxt->sax->cdataBlock != NULL) &&
11204                         (!ctxt->disableSAX)) {
11205                         /*
11206                          * Special case to provide identical behaviour
11207                          * between pull and push parsers on enpty CDATA
11208                          * sections
11209                          */
11210                          if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11211                              (!strncmp((const char *)&ctxt->input->cur[-9],
11212                                        "<![CDATA[", 9)))
11213                              ctxt->sax->cdataBlock(ctxt->userData,
11214                                                    BAD_CAST "", 0);
11215                     } else if ((ctxt->sax != NULL) && (base > 0) &&
11216                         (!ctxt->disableSAX)) {
11217                         if (ctxt->sax->cdataBlock != NULL)
11218                             ctxt->sax->cdataBlock(ctxt->userData,
11219                                                   ctxt->input->cur, base);
11220                         else if (ctxt->sax->characters != NULL)
11221                             ctxt->sax->characters(ctxt->userData,
11222                                                   ctxt->input->cur, base);
11223                     }
11224                     SKIPL(base + 3);
11225                     ctxt->checkIndex = 0;
11226                     ctxt->instate = XML_PARSER_CONTENT;
11227 #ifdef DEBUG_PUSH
11228                     xmlGenericError(xmlGenericErrorContext,
11229                             "PP: entering CONTENT\n");
11230 #endif
11231                 }
11232                 break;
11233             }
11234             case XML_PARSER_MISC:
11235                 SKIP_BLANKS;
11236                 if (ctxt->input->buf == NULL)
11237                     avail = ctxt->input->length -
11238                             (ctxt->input->cur - ctxt->input->base);
11239                 else
11240                     avail = ctxt->input->buf->buffer->use -
11241                             (ctxt->input->cur - ctxt->input->base);
11242                 if (avail < 2)
11243                     goto done;
11244                 cur = ctxt->input->cur[0];
11245                 next = ctxt->input->cur[1];
11246                 if ((cur == '<') && (next == '?')) {
11247                     if ((!terminate) &&
11248                         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11249                         goto done;
11250 #ifdef DEBUG_PUSH
11251                     xmlGenericError(xmlGenericErrorContext,
11252                             "PP: Parsing PI\n");
11253 #endif
11254                     xmlParsePI(ctxt);
11255                     ctxt->checkIndex = 0;
11256                 } else if ((cur == '<') && (next == '!') &&
11257                     (ctxt->input->cur[2] == '-') &&
11258                     (ctxt->input->cur[3] == '-')) {
11259                     if ((!terminate) &&
11260                         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11261                         goto done;
11262 #ifdef DEBUG_PUSH
11263                     xmlGenericError(xmlGenericErrorContext,
11264                             "PP: Parsing Comment\n");
11265 #endif
11266                     xmlParseComment(ctxt);
11267                     ctxt->instate = XML_PARSER_MISC;
11268                     ctxt->checkIndex = 0;
11269                 } else if ((cur == '<') && (next == '!') &&
11270                     (ctxt->input->cur[2] == 'D') &&
11271                     (ctxt->input->cur[3] == 'O') &&
11272                     (ctxt->input->cur[4] == 'C') &&
11273                     (ctxt->input->cur[5] == 'T') &&
11274                     (ctxt->input->cur[6] == 'Y') &&
11275                     (ctxt->input->cur[7] == 'P') &&
11276                     (ctxt->input->cur[8] == 'E')) {
11277                     if ((!terminate) &&
11278                         (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
11279                         goto done;
11280 #ifdef DEBUG_PUSH
11281                     xmlGenericError(xmlGenericErrorContext,
11282                             "PP: Parsing internal subset\n");
11283 #endif
11284                     ctxt->inSubset = 1;
11285                     xmlParseDocTypeDecl(ctxt);
11286                     if (RAW == '[') {
11287                         ctxt->instate = XML_PARSER_DTD;
11288 #ifdef DEBUG_PUSH
11289                         xmlGenericError(xmlGenericErrorContext,
11290                                 "PP: entering DTD\n");
11291 #endif
11292                     } else {
11293                         /*
11294                          * Create and update the external subset.
11295                          */
11296                         ctxt->inSubset = 2;
11297                         if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11298                             (ctxt->sax->externalSubset != NULL))
11299                             ctxt->sax->externalSubset(ctxt->userData,
11300                                     ctxt->intSubName, ctxt->extSubSystem,
11301                                     ctxt->extSubURI);
11302                         ctxt->inSubset = 0;
11303                         xmlCleanSpecialAttr(ctxt);
11304                         ctxt->instate = XML_PARSER_PROLOG;
11305 #ifdef DEBUG_PUSH
11306                         xmlGenericError(xmlGenericErrorContext,
11307                                 "PP: entering PROLOG\n");
11308 #endif
11309                     }
11310                 } else if ((cur == '<') && (next == '!') &&
11311                            (avail < 9)) {
11312                     goto done;
11313                 } else {
11314                     ctxt->instate = XML_PARSER_START_TAG;
11315                     ctxt->progressive = 1;
11316                     xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11317 #ifdef DEBUG_PUSH
11318                     xmlGenericError(xmlGenericErrorContext,
11319                             "PP: entering START_TAG\n");
11320 #endif
11321                 }
11322                 break;
11323             case XML_PARSER_PROLOG:
11324                 SKIP_BLANKS;
11325                 if (ctxt->input->buf == NULL)
11326                     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11327                 else
11328                     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
11329                 if (avail < 2) 
11330                     goto done;
11331                 cur = ctxt->input->cur[0];
11332                 next = ctxt->input->cur[1];
11333                 if ((cur == '<') && (next == '?')) {
11334                     if ((!terminate) &&
11335                         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11336                         goto done;
11337 #ifdef DEBUG_PUSH
11338                     xmlGenericError(xmlGenericErrorContext,
11339                             "PP: Parsing PI\n");
11340 #endif
11341                     xmlParsePI(ctxt);
11342                 } else if ((cur == '<') && (next == '!') &&
11343                     (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11344                     if ((!terminate) &&
11345                         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11346                         goto done;
11347 #ifdef DEBUG_PUSH
11348                     xmlGenericError(xmlGenericErrorContext,
11349                             "PP: Parsing Comment\n");
11350 #endif
11351                     xmlParseComment(ctxt);
11352                     ctxt->instate = XML_PARSER_PROLOG;
11353                 } else if ((cur == '<') && (next == '!') &&
11354                            (avail < 4)) {
11355                     goto done;
11356                 } else {
11357                     ctxt->instate = XML_PARSER_START_TAG;
11358                     if (ctxt->progressive == 0)
11359                         ctxt->progressive = 1;
11360                     xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11361 #ifdef DEBUG_PUSH
11362                     xmlGenericError(xmlGenericErrorContext,
11363                             "PP: entering START_TAG\n");
11364 #endif
11365                 }
11366                 break;
11367             case XML_PARSER_EPILOG:
11368                 SKIP_BLANKS;
11369                 if (ctxt->input->buf == NULL)
11370                     avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11371                 else
11372                     avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
11373                 if (avail < 2)
11374                     goto done;
11375                 cur = ctxt->input->cur[0];
11376                 next = ctxt->input->cur[1];
11377                 if ((cur == '<') && (next == '?')) {
11378                     if ((!terminate) &&
11379                         (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11380                         goto done;
11381 #ifdef DEBUG_PUSH
11382                     xmlGenericError(xmlGenericErrorContext,
11383                             "PP: Parsing PI\n");
11384 #endif
11385                     xmlParsePI(ctxt);
11386                     ctxt->instate = XML_PARSER_EPILOG;
11387                 } else if ((cur == '<') && (next == '!') &&
11388                     (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11389                     if ((!terminate) &&
11390                         (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11391                         goto done;
11392 #ifdef DEBUG_PUSH
11393                     xmlGenericError(xmlGenericErrorContext,
11394                             "PP: Parsing Comment\n");
11395 #endif
11396                     xmlParseComment(ctxt);
11397                     ctxt->instate = XML_PARSER_EPILOG;
11398                 } else if ((cur == '<') && (next == '!') &&
11399                            (avail < 4)) {
11400                     goto done;
11401                 } else {
11402                     xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11403                     ctxt->instate = XML_PARSER_EOF;
11404 #ifdef DEBUG_PUSH
11405                     xmlGenericError(xmlGenericErrorContext,
11406                             "PP: entering EOF\n");
11407 #endif
11408                     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11409                         ctxt->sax->endDocument(ctxt->userData);
11410                     goto done;
11411                 }
11412                 break;
11413             case XML_PARSER_DTD: {
11414                 /*
11415                  * Sorry but progressive parsing of the internal subset
11416                  * is not expected to be supported. We first check that
11417                  * the full content of the internal subset is available and
11418                  * the parsing is launched only at that point.
11419                  * Internal subset ends up with "']' S? '>'" in an unescaped
11420                  * section and not in a ']]>' sequence which are conditional
11421                  * sections (whoever argued to keep that crap in XML deserve
11422                  * a place in hell !).
11423                  */
11424                 int base, i;
11425                 xmlChar *buf;
11426                 xmlChar quote = 0;
11427
11428                 base = ctxt->input->cur - ctxt->input->base;
11429                 if (base < 0) return(0);
11430                 if (ctxt->checkIndex > base)
11431                     base = ctxt->checkIndex;
11432                 buf = ctxt->input->buf->buffer->content;
11433                 for (;(unsigned int) base < ctxt->input->buf->buffer->use;
11434                      base++) {
11435                     if (quote != 0) {
11436                         if (buf[base] == quote)
11437                             quote = 0;
11438                         continue;    
11439                     }
11440                     if ((quote == 0) && (buf[base] == '<')) {
11441                         int found  = 0;
11442                         /* special handling of comments */
11443                         if (((unsigned int) base + 4 <
11444                              ctxt->input->buf->buffer->use) &&
11445                             (buf[base + 1] == '!') &&
11446                             (buf[base + 2] == '-') &&
11447                             (buf[base + 3] == '-')) {
11448                             for (;(unsigned int) base + 3 <
11449                                   ctxt->input->buf->buffer->use; base++) {
11450                                 if ((buf[base] == '-') &&
11451                                     (buf[base + 1] == '-') &&
11452                                     (buf[base + 2] == '>')) {
11453                                     found = 1;
11454                                     base += 2;
11455                                     break;
11456                                 }
11457                             }
11458                             if (!found) {
11459 #if 0
11460                                 fprintf(stderr, "unfinished comment\n");
11461 #endif
11462                                 break; /* for */
11463                             }
11464                             continue;
11465                         }
11466                     }
11467                     if (buf[base] == '"') {
11468                         quote = '"';
11469                         continue;
11470                     }
11471                     if (buf[base] == '\'') {
11472                         quote = '\'';
11473                         continue;
11474                     }
11475                     if (buf[base] == ']') {
11476 #if 0
11477                         fprintf(stderr, "%c%c%c%c: ", buf[base],
11478                                 buf[base + 1], buf[base + 2], buf[base + 3]);
11479 #endif
11480                         if ((unsigned int) base +1 >=
11481                             ctxt->input->buf->buffer->use)
11482                             break;
11483                         if (buf[base + 1] == ']') {
11484                             /* conditional crap, skip both ']' ! */
11485                             base++;
11486                             continue;
11487                         }
11488                         for (i = 1;
11489                      (unsigned int) base + i < ctxt->input->buf->buffer->use;
11490                              i++) {
11491                             if (buf[base + i] == '>') {
11492 #if 0
11493                                 fprintf(stderr, "found\n");
11494 #endif
11495                                 goto found_end_int_subset;
11496                             }
11497                             if (!IS_BLANK_CH(buf[base + i])) {
11498 #if 0
11499                                 fprintf(stderr, "not found\n");
11500 #endif
11501                                 goto not_end_of_int_subset;
11502                             }
11503                         }
11504 #if 0
11505                         fprintf(stderr, "end of stream\n");
11506 #endif
11507                         break;
11508                         
11509                     }
11510 not_end_of_int_subset:
11511                     continue; /* for */
11512                 }
11513                 /*
11514                  * We didn't found the end of the Internal subset
11515                  */
11516 #ifdef DEBUG_PUSH
11517                 if (next == 0)
11518                     xmlGenericError(xmlGenericErrorContext,
11519                             "PP: lookup of int subset end filed\n");
11520 #endif
11521                 goto done;
11522
11523 found_end_int_subset:
11524                 xmlParseInternalSubset(ctxt);
11525                 ctxt->inSubset = 2;
11526                 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11527                     (ctxt->sax->externalSubset != NULL))
11528                     ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11529                             ctxt->extSubSystem, ctxt->extSubURI);
11530                 ctxt->inSubset = 0;
11531                 xmlCleanSpecialAttr(ctxt);
11532                 ctxt->instate = XML_PARSER_PROLOG;
11533                 ctxt->checkIndex = 0;
11534 #ifdef DEBUG_PUSH
11535                 xmlGenericError(xmlGenericErrorContext,
11536                         "PP: entering PROLOG\n");
11537 #endif
11538                 break;
11539             }
11540             case XML_PARSER_COMMENT:
11541                 xmlGenericError(xmlGenericErrorContext,
11542                         "PP: internal error, state == COMMENT\n");
11543                 ctxt->instate = XML_PARSER_CONTENT;
11544 #ifdef DEBUG_PUSH
11545                 xmlGenericError(xmlGenericErrorContext,
11546                         "PP: entering CONTENT\n");
11547 #endif
11548                 break;
11549             case XML_PARSER_IGNORE:
11550                 xmlGenericError(xmlGenericErrorContext,
11551                         "PP: internal error, state == IGNORE");
11552                 ctxt->instate = XML_PARSER_DTD;
11553 #ifdef DEBUG_PUSH
11554                 xmlGenericError(xmlGenericErrorContext,
11555                         "PP: entering DTD\n");
11556 #endif
11557                 break;
11558             case XML_PARSER_PI:
11559                 xmlGenericError(xmlGenericErrorContext,
11560                         "PP: internal error, state == PI\n");
11561                 ctxt->instate = XML_PARSER_CONTENT;
11562 #ifdef DEBUG_PUSH
11563                 xmlGenericError(xmlGenericErrorContext,
11564                         "PP: entering CONTENT\n");
11565 #endif
11566                 break;
11567             case XML_PARSER_ENTITY_DECL:
11568                 xmlGenericError(xmlGenericErrorContext,
11569                         "PP: internal error, state == ENTITY_DECL\n");
11570                 ctxt->instate = XML_PARSER_DTD;
11571 #ifdef DEBUG_PUSH
11572                 xmlGenericError(xmlGenericErrorContext,
11573                         "PP: entering DTD\n");
11574 #endif
11575                 break;
11576             case XML_PARSER_ENTITY_VALUE:
11577                 xmlGenericError(xmlGenericErrorContext,
11578                         "PP: internal error, state == ENTITY_VALUE\n");
11579                 ctxt->instate = XML_PARSER_CONTENT;
11580 #ifdef DEBUG_PUSH
11581                 xmlGenericError(xmlGenericErrorContext,
11582                         "PP: entering DTD\n");
11583 #endif
11584                 break;
11585             case XML_PARSER_ATTRIBUTE_VALUE:
11586                 xmlGenericError(xmlGenericErrorContext,
11587                         "PP: internal error, state == ATTRIBUTE_VALUE\n");
11588                 ctxt->instate = XML_PARSER_START_TAG;
11589 #ifdef DEBUG_PUSH
11590                 xmlGenericError(xmlGenericErrorContext,
11591                         "PP: entering START_TAG\n");
11592 #endif
11593                 break;
11594             case XML_PARSER_SYSTEM_LITERAL:
11595                 xmlGenericError(xmlGenericErrorContext,
11596                         "PP: internal error, state == SYSTEM_LITERAL\n");
11597                 ctxt->instate = XML_PARSER_START_TAG;
11598 #ifdef DEBUG_PUSH
11599                 xmlGenericError(xmlGenericErrorContext,
11600                         "PP: entering START_TAG\n");
11601 #endif
11602                 break;
11603             case XML_PARSER_PUBLIC_LITERAL:
11604                 xmlGenericError(xmlGenericErrorContext,
11605                         "PP: internal error, state == PUBLIC_LITERAL\n");
11606                 ctxt->instate = XML_PARSER_START_TAG;
11607 #ifdef DEBUG_PUSH
11608                 xmlGenericError(xmlGenericErrorContext,
11609                         "PP: entering START_TAG\n");
11610 #endif
11611                 break;
11612         }
11613     }
11614 done:    
11615 #ifdef DEBUG_PUSH
11616     xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
11617 #endif
11618     return(ret);
11619 encoding_error:
11620     {
11621         char buffer[150];
11622
11623         snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
11624                         ctxt->input->cur[0], ctxt->input->cur[1],
11625                         ctxt->input->cur[2], ctxt->input->cur[3]);
11626         __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
11627                      "Input is not proper UTF-8, indicate encoding !\n%s",
11628                      BAD_CAST buffer, NULL);
11629     }
11630     return(0);
11631 }
11632
11633 /**
11634  * xmlParseChunk:
11635  * @ctxt:  an XML parser context
11636  * @chunk:  an char array
11637  * @size:  the size in byte of the chunk
11638  * @terminate:  last chunk indicator
11639  *
11640  * Parse a Chunk of memory
11641  *
11642  * Returns zero if no error, the xmlParserErrors otherwise.
11643  */
11644 int
11645 xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
11646               int terminate) {
11647     int end_in_lf = 0;
11648     int remain = 0;
11649
11650     if (ctxt == NULL)
11651         return(XML_ERR_INTERNAL_ERROR);
11652     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11653         return(ctxt->errNo);
11654     if (ctxt->instate == XML_PARSER_START)
11655         xmlDetectSAX2(ctxt);
11656     if ((size > 0) && (chunk != NULL) && (!terminate) &&
11657         (chunk[size - 1] == '\r')) {
11658         end_in_lf = 1;
11659         size--;
11660     }
11661
11662 xmldecl_done:
11663
11664     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
11665         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
11666         int base = ctxt->input->base - ctxt->input->buf->buffer->content;
11667         int cur = ctxt->input->cur - ctxt->input->base;
11668         int res;
11669
11670         /*
11671          * Specific handling if we autodetected an encoding, we should not
11672          * push more than the first line ... which depend on the encoding
11673          * And only push the rest once the final encoding was detected
11674          */
11675         if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
11676             (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
11677             unsigned int len = 45;
11678
11679             if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11680                                BAD_CAST "UTF-16")) ||
11681                 (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11682                                BAD_CAST "UTF16")))
11683                 len = 90;
11684             else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11685                                     BAD_CAST "UCS-4")) ||
11686                      (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11687                                     BAD_CAST "UCS4")))
11688                 len = 180;
11689
11690             if (ctxt->input->buf->rawconsumed < len)
11691                 len -= ctxt->input->buf->rawconsumed;
11692
11693             /*
11694              * Change size for reading the initial declaration only
11695              * if size is greater than len. Otherwise, memmove in xmlBufferAdd
11696              * will blindly copy extra bytes from memory.
11697              */
11698             if ((unsigned int) size > len) {
11699                 remain = size - len;
11700                 size = len;
11701             } else {
11702                 remain = 0;
11703             }
11704         }
11705         res =xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
11706         if (res < 0) {
11707             ctxt->errNo = XML_PARSER_EOF;
11708             ctxt->disableSAX = 1;
11709             return (XML_PARSER_EOF);
11710         }
11711         ctxt->input->base = ctxt->input->buf->buffer->content + base;
11712         ctxt->input->cur = ctxt->input->base + cur;
11713         ctxt->input->end =
11714             &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
11715 #ifdef DEBUG_PUSH
11716         xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
11717 #endif
11718
11719     } else if (ctxt->instate != XML_PARSER_EOF) {
11720         if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
11721             xmlParserInputBufferPtr in = ctxt->input->buf;
11722             if ((in->encoder != NULL) && (in->buffer != NULL) &&
11723                     (in->raw != NULL)) {
11724                 int nbchars;
11725
11726                 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
11727                 if (nbchars < 0) {
11728                     /* TODO 2.6.0 */
11729                     xmlGenericError(xmlGenericErrorContext,
11730                                     "xmlParseChunk: encoder error\n");
11731                     return(XML_ERR_INVALID_ENCODING);
11732                 }
11733             }
11734         }
11735     }
11736     if (remain != 0)
11737         xmlParseTryOrFinish(ctxt, 0);
11738     else
11739         xmlParseTryOrFinish(ctxt, terminate);
11740     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11741         return(ctxt->errNo);
11742
11743     if (remain != 0) {
11744         chunk += size;
11745         size = remain;
11746         remain = 0;
11747         goto xmldecl_done;
11748     }
11749     if ((end_in_lf == 1) && (ctxt->input != NULL) &&
11750         (ctxt->input->buf != NULL)) {
11751         xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
11752     }
11753     if (terminate) {
11754         /*
11755          * Check for termination
11756          */
11757         int avail = 0;
11758
11759         if (ctxt->input != NULL) {
11760             if (ctxt->input->buf == NULL)
11761                 avail = ctxt->input->length -
11762                         (ctxt->input->cur - ctxt->input->base);
11763             else
11764                 avail = ctxt->input->buf->buffer->use -
11765                         (ctxt->input->cur - ctxt->input->base);
11766         }
11767                             
11768         if ((ctxt->instate != XML_PARSER_EOF) &&
11769             (ctxt->instate != XML_PARSER_EPILOG)) {
11770             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11771         } 
11772         if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
11773             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11774         }
11775         if (ctxt->instate != XML_PARSER_EOF) {
11776             if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11777                 ctxt->sax->endDocument(ctxt->userData);
11778         }
11779         ctxt->instate = XML_PARSER_EOF;
11780     }
11781     return((xmlParserErrors) ctxt->errNo);            
11782 }
11783
11784 /************************************************************************
11785  *                                                                      *
11786  *              I/O front end functions to the parser                   *
11787  *                                                                      *
11788  ************************************************************************/
11789
11790 /**
11791  * xmlCreatePushParserCtxt:
11792  * @sax:  a SAX handler
11793  * @user_data:  The user data returned on SAX callbacks
11794  * @chunk:  a pointer to an array of chars
11795  * @size:  number of chars in the array
11796  * @filename:  an optional file name or URI
11797  *
11798  * Create a parser context for using the XML parser in push mode.
11799  * If @buffer and @size are non-NULL, the data is used to detect
11800  * the encoding.  The remaining characters will be parsed so they
11801  * don't need to be fed in again through xmlParseChunk.
11802  * To allow content encoding detection, @size should be >= 4
11803  * The value of @filename is used for fetching external entities
11804  * and error/warning reports.
11805  *
11806  * Returns the new parser context or NULL
11807  */
11808
11809 xmlParserCtxtPtr
11810 xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 
11811                         const char *chunk, int size, const char *filename) {
11812     xmlParserCtxtPtr ctxt;
11813     xmlParserInputPtr inputStream;
11814     xmlParserInputBufferPtr buf;
11815     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
11816
11817     /*
11818      * plug some encoding conversion routines
11819      */
11820     if ((chunk != NULL) && (size >= 4))
11821         enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
11822
11823     buf = xmlAllocParserInputBuffer(enc);
11824     if (buf == NULL) return(NULL);
11825
11826     ctxt = xmlNewParserCtxt();
11827     if (ctxt == NULL) {
11828         xmlErrMemory(NULL, "creating parser: out of memory\n");
11829         xmlFreeParserInputBuffer(buf);
11830         return(NULL);
11831     }
11832     ctxt->dictNames = 1;
11833     ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
11834     if (ctxt->pushTab == NULL) {
11835         xmlErrMemory(ctxt, NULL);
11836         xmlFreeParserInputBuffer(buf);
11837         xmlFreeParserCtxt(ctxt);
11838         return(NULL);
11839     }
11840     if (sax != NULL) {
11841 #ifdef LIBXML_SAX1_ENABLED
11842         if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
11843 #endif /* LIBXML_SAX1_ENABLED */
11844             xmlFree(ctxt->sax);
11845         ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
11846         if (ctxt->sax == NULL) {
11847             xmlErrMemory(ctxt, NULL);
11848             xmlFreeParserInputBuffer(buf);
11849             xmlFreeParserCtxt(ctxt);
11850             return(NULL);
11851         }
11852         memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
11853         if (sax->initialized == XML_SAX2_MAGIC)
11854             memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
11855         else
11856             memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
11857         if (user_data != NULL)
11858             ctxt->userData = user_data;
11859     }   
11860     if (filename == NULL) {
11861         ctxt->directory = NULL;
11862     } else {
11863         ctxt->directory = xmlParserGetDirectory(filename);
11864     }
11865
11866     inputStream = xmlNewInputStream(ctxt);
11867     if (inputStream == NULL) {
11868         xmlFreeParserCtxt(ctxt);
11869         xmlFreeParserInputBuffer(buf);
11870         return(NULL);
11871     }
11872
11873     if (filename == NULL)
11874         inputStream->filename = NULL;
11875     else {
11876         inputStream->filename = (char *)
11877             xmlCanonicPath((const xmlChar *) filename);
11878         if (inputStream->filename == NULL) {
11879             xmlFreeParserCtxt(ctxt);
11880             xmlFreeParserInputBuffer(buf);
11881             return(NULL);
11882         }
11883     }
11884     inputStream->buf = buf;
11885     inputStream->base = inputStream->buf->buffer->content;
11886     inputStream->cur = inputStream->buf->buffer->content;
11887     inputStream->end = 
11888         &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
11889
11890     inputPush(ctxt, inputStream);
11891
11892     /*
11893      * If the caller didn't provide an initial 'chunk' for determining
11894      * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
11895      * that it can be automatically determined later
11896      */
11897     if ((size == 0) || (chunk == NULL)) {
11898         ctxt->charset = XML_CHAR_ENCODING_NONE;
11899     } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
11900         int base = ctxt->input->base - ctxt->input->buf->buffer->content;
11901         int cur = ctxt->input->cur - ctxt->input->base;
11902
11903         xmlParserInputBufferPush(ctxt->input->buf, size, chunk);              
11904
11905         ctxt->input->base = ctxt->input->buf->buffer->content + base;
11906         ctxt->input->cur = ctxt->input->base + cur;
11907         ctxt->input->end =
11908             &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
11909 #ifdef DEBUG_PUSH
11910         xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
11911 #endif
11912     }
11913
11914     if (enc != XML_CHAR_ENCODING_NONE) {
11915         xmlSwitchEncoding(ctxt, enc);
11916     }
11917
11918     return(ctxt);
11919 }
11920 #endif /* LIBXML_PUSH_ENABLED */
11921
11922 /**
11923  * xmlStopParser:
11924  * @ctxt:  an XML parser context
11925  *
11926  * Blocks further parser processing
11927  */
11928 void           
11929 xmlStopParser(xmlParserCtxtPtr ctxt) {
11930     if (ctxt == NULL)
11931         return;
11932     ctxt->instate = XML_PARSER_EOF;
11933     ctxt->disableSAX = 1;
11934     if (ctxt->input != NULL) {
11935         ctxt->input->cur = BAD_CAST"";
11936         ctxt->input->base = ctxt->input->cur;
11937     }
11938 }
11939
11940 /**
11941  * xmlCreateIOParserCtxt:
11942  * @sax:  a SAX handler
11943  * @user_data:  The user data returned on SAX callbacks
11944  * @ioread:  an I/O read function
11945  * @ioclose:  an I/O close function
11946  * @ioctx:  an I/O handler
11947  * @enc:  the charset encoding if known
11948  *
11949  * Create a parser context for using the XML parser with an existing
11950  * I/O stream
11951  *
11952  * Returns the new parser context or NULL
11953  */
11954 xmlParserCtxtPtr
11955 xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
11956         xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
11957         void *ioctx, xmlCharEncoding enc) {
11958     xmlParserCtxtPtr ctxt;
11959     xmlParserInputPtr inputStream;
11960     xmlParserInputBufferPtr buf;
11961     
11962     if (ioread == NULL) return(NULL);
11963
11964     buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
11965     if (buf == NULL) return(NULL);
11966
11967     ctxt = xmlNewParserCtxt();
11968     if (ctxt == NULL) {
11969         xmlFreeParserInputBuffer(buf);
11970         return(NULL);
11971     }
11972     if (sax != NULL) {
11973 #ifdef LIBXML_SAX1_ENABLED
11974         if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
11975 #endif /* LIBXML_SAX1_ENABLED */
11976             xmlFree(ctxt->sax);
11977         ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
11978         if (ctxt->sax == NULL) {
11979             xmlErrMemory(ctxt, NULL);
11980             xmlFreeParserCtxt(ctxt);
11981             return(NULL);
11982         }
11983         memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
11984         if (sax->initialized == XML_SAX2_MAGIC)
11985             memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
11986         else
11987             memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
11988         if (user_data != NULL)
11989             ctxt->userData = user_data;
11990     }   
11991
11992     inputStream = xmlNewIOInputStream(ctxt, buf, enc);
11993     if (inputStream == NULL) {
11994         xmlFreeParserCtxt(ctxt);
11995         return(NULL);
11996     }
11997     inputPush(ctxt, inputStream);
11998
11999     return(ctxt);
12000 }
12001
12002 #ifdef LIBXML_VALID_ENABLED
12003 /************************************************************************
12004  *                                                                      *
12005  *              Front ends when parsing a DTD                           *
12006  *                                                                      *
12007  ************************************************************************/
12008
12009 /**
12010  * xmlIOParseDTD:
12011  * @sax:  the SAX handler block or NULL
12012  * @input:  an Input Buffer
12013  * @enc:  the charset encoding if known
12014  *
12015  * Load and parse a DTD
12016  * 
12017  * Returns the resulting xmlDtdPtr or NULL in case of error.
12018  * @input will be freed by the function in any case.
12019  */
12020
12021 xmlDtdPtr
12022 xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12023               xmlCharEncoding enc) {
12024     xmlDtdPtr ret = NULL;
12025     xmlParserCtxtPtr ctxt;
12026     xmlParserInputPtr pinput = NULL;
12027     xmlChar start[4];
12028
12029     if (input == NULL)
12030         return(NULL);
12031
12032     ctxt = xmlNewParserCtxt();
12033     if (ctxt == NULL) {
12034         xmlFreeParserInputBuffer(input);
12035         return(NULL);
12036     }
12037
12038     /*
12039      * Set-up the SAX context
12040      */
12041     if (sax != NULL) { 
12042         if (ctxt->sax != NULL)
12043             xmlFree(ctxt->sax);
12044         ctxt->sax = sax;
12045         ctxt->userData = ctxt;
12046     }
12047     xmlDetectSAX2(ctxt);
12048
12049     /*
12050      * generate a parser input from the I/O handler
12051      */
12052
12053     pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12054     if (pinput == NULL) {
12055         if (sax != NULL) ctxt->sax = NULL;
12056         xmlFreeParserInputBuffer(input);
12057         xmlFreeParserCtxt(ctxt);
12058         return(NULL);
12059     }
12060
12061     /*
12062      * plug some encoding conversion routines here.
12063      */
12064     if (xmlPushInput(ctxt, pinput) < 0) {
12065         if (sax != NULL) ctxt->sax = NULL;
12066         xmlFreeParserCtxt(ctxt);
12067         return(NULL);
12068     }
12069     if (enc != XML_CHAR_ENCODING_NONE) {
12070         xmlSwitchEncoding(ctxt, enc);
12071     }
12072
12073     pinput->filename = NULL;
12074     pinput->line = 1;
12075     pinput->col = 1;
12076     pinput->base = ctxt->input->cur;
12077     pinput->cur = ctxt->input->cur;
12078     pinput->free = NULL;
12079
12080     /*
12081      * let's parse that entity knowing it's an external subset.
12082      */
12083     ctxt->inSubset = 2;
12084     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12085     if (ctxt->myDoc == NULL) {
12086         xmlErrMemory(ctxt, "New Doc failed");
12087         return(NULL);
12088     }
12089     ctxt->myDoc->properties = XML_DOC_INTERNAL;
12090     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12091                                        BAD_CAST "none", BAD_CAST "none");
12092
12093     if ((enc == XML_CHAR_ENCODING_NONE) &&
12094         ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12095         /* 
12096          * Get the 4 first bytes and decode the charset
12097          * if enc != XML_CHAR_ENCODING_NONE
12098          * plug some encoding conversion routines.
12099          */
12100         start[0] = RAW;
12101         start[1] = NXT(1);
12102         start[2] = NXT(2);
12103         start[3] = NXT(3);
12104         enc = xmlDetectCharEncoding(start, 4);
12105         if (enc != XML_CHAR_ENCODING_NONE) {
12106             xmlSwitchEncoding(ctxt, enc);
12107         }
12108     }
12109
12110     xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12111
12112     if (ctxt->myDoc != NULL) {
12113         if (ctxt->wellFormed) {
12114             ret = ctxt->myDoc->extSubset;
12115             ctxt->myDoc->extSubset = NULL;
12116             if (ret != NULL) {
12117                 xmlNodePtr tmp;
12118
12119                 ret->doc = NULL;
12120                 tmp = ret->children;
12121                 while (tmp != NULL) {
12122                     tmp->doc = NULL;
12123                     tmp = tmp->next;
12124                 }
12125             }
12126         } else {
12127             ret = NULL;
12128         }
12129         xmlFreeDoc(ctxt->myDoc);
12130         ctxt->myDoc = NULL;
12131     }
12132     if (sax != NULL) ctxt->sax = NULL;
12133     xmlFreeParserCtxt(ctxt);
12134     
12135     return(ret);
12136 }
12137
12138 /**
12139  * xmlSAXParseDTD:
12140  * @sax:  the SAX handler block
12141  * @ExternalID:  a NAME* containing the External ID of the DTD
12142  * @SystemID:  a NAME* containing the URL to the DTD
12143  *
12144  * Load and parse an external subset.
12145  * 
12146  * Returns the resulting xmlDtdPtr or NULL in case of error.
12147  */
12148
12149 xmlDtdPtr
12150 xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12151                           const xmlChar *SystemID) {
12152     xmlDtdPtr ret = NULL;
12153     xmlParserCtxtPtr ctxt;
12154     xmlParserInputPtr input = NULL;
12155     xmlCharEncoding enc;
12156     xmlChar* systemIdCanonic;
12157
12158     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12159
12160     ctxt = xmlNewParserCtxt();
12161     if (ctxt == NULL) {
12162         return(NULL);
12163     }
12164
12165     /*
12166      * Set-up the SAX context
12167      */
12168     if (sax != NULL) { 
12169         if (ctxt->sax != NULL)
12170             xmlFree(ctxt->sax);
12171         ctxt->sax = sax;
12172         ctxt->userData = ctxt;
12173     }
12174     
12175     /*
12176      * Canonicalise the system ID
12177      */
12178     systemIdCanonic = xmlCanonicPath(SystemID);
12179     if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12180         xmlFreeParserCtxt(ctxt);
12181         return(NULL);
12182     }
12183
12184     /*
12185      * Ask the Entity resolver to load the damn thing
12186      */
12187
12188     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12189         input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12190                                          systemIdCanonic);
12191     if (input == NULL) {
12192         if (sax != NULL) ctxt->sax = NULL;
12193         xmlFreeParserCtxt(ctxt);
12194         if (systemIdCanonic != NULL)
12195             xmlFree(systemIdCanonic);
12196         return(NULL);
12197     }
12198
12199     /*
12200      * plug some encoding conversion routines here.
12201      */
12202     if (xmlPushInput(ctxt, input) < 0) {
12203         if (sax != NULL) ctxt->sax = NULL;
12204         xmlFreeParserCtxt(ctxt);
12205         if (systemIdCanonic != NULL)
12206             xmlFree(systemIdCanonic);
12207         return(NULL);
12208     }
12209     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12210         enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12211         xmlSwitchEncoding(ctxt, enc);
12212     }
12213
12214     if (input->filename == NULL)
12215         input->filename = (char *) systemIdCanonic;
12216     else
12217         xmlFree(systemIdCanonic);
12218     input->line = 1;
12219     input->col = 1;
12220     input->base = ctxt->input->cur;
12221     input->cur = ctxt->input->cur;
12222     input->free = NULL;
12223
12224     /*
12225      * let's parse that entity knowing it's an external subset.
12226      */
12227     ctxt->inSubset = 2;
12228     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12229     if (ctxt->myDoc == NULL) {
12230         xmlErrMemory(ctxt, "New Doc failed");
12231         if (sax != NULL) ctxt->sax = NULL;
12232         xmlFreeParserCtxt(ctxt);
12233         return(NULL);
12234     }
12235     ctxt->myDoc->properties = XML_DOC_INTERNAL;
12236     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12237                                        ExternalID, SystemID);
12238     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12239
12240     if (ctxt->myDoc != NULL) {
12241         if (ctxt->wellFormed) {
12242             ret = ctxt->myDoc->extSubset;
12243             ctxt->myDoc->extSubset = NULL;
12244             if (ret != NULL) {
12245                 xmlNodePtr tmp;
12246
12247                 ret->doc = NULL;
12248                 tmp = ret->children;
12249                 while (tmp != NULL) {
12250                     tmp->doc = NULL;
12251                     tmp = tmp->next;
12252                 }
12253             }
12254         } else {
12255             ret = NULL;
12256         }
12257         xmlFreeDoc(ctxt->myDoc);
12258         ctxt->myDoc = NULL;
12259     }
12260     if (sax != NULL) ctxt->sax = NULL;
12261     xmlFreeParserCtxt(ctxt);
12262
12263     return(ret);
12264 }
12265
12266
12267 /**
12268  * xmlParseDTD:
12269  * @ExternalID:  a NAME* containing the External ID of the DTD
12270  * @SystemID:  a NAME* containing the URL to the DTD
12271  *
12272  * Load and parse an external subset.
12273  *
12274  * Returns the resulting xmlDtdPtr or NULL in case of error.
12275  */
12276
12277 xmlDtdPtr
12278 xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12279     return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12280 }
12281 #endif /* LIBXML_VALID_ENABLED */
12282
12283 /************************************************************************
12284  *                                                                      *
12285  *              Front ends when parsing an Entity                       *
12286  *                                                                      *
12287  ************************************************************************/
12288
12289 /**
12290  * xmlParseCtxtExternalEntity:
12291  * @ctx:  the existing parsing context
12292  * @URL:  the URL for the entity to load
12293  * @ID:  the System ID for the entity to load
12294  * @lst:  the return value for the set of parsed nodes
12295  *
12296  * Parse an external general entity within an existing parsing context
12297  * An external general parsed entity is well-formed if it matches the
12298  * production labeled extParsedEnt.
12299  *
12300  * [78] extParsedEnt ::= TextDecl? content
12301  *
12302  * Returns 0 if the entity is well formed, -1 in case of args problem and
12303  *    the parser error code otherwise
12304  */
12305
12306 int
12307 xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12308                        const xmlChar *ID, xmlNodePtr *lst) {
12309     xmlParserCtxtPtr ctxt;
12310     xmlDocPtr newDoc;
12311     xmlNodePtr newRoot;
12312     xmlSAXHandlerPtr oldsax = NULL;
12313     int ret = 0;
12314     xmlChar start[4];
12315     xmlCharEncoding enc;
12316
12317     if (ctx == NULL) return(-1);
12318
12319     if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
12320         (ctx->depth > 1024)) {
12321         return(XML_ERR_ENTITY_LOOP);
12322     }
12323
12324     if (lst != NULL)
12325         *lst = NULL;
12326     if ((URL == NULL) && (ID == NULL))
12327         return(-1);
12328     if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
12329         return(-1);
12330
12331     ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
12332     if (ctxt == NULL) {
12333         return(-1);
12334     }
12335
12336     oldsax = ctxt->sax;
12337     ctxt->sax = ctx->sax;
12338     xmlDetectSAX2(ctxt);
12339     newDoc = xmlNewDoc(BAD_CAST "1.0");
12340     if (newDoc == NULL) {
12341         xmlFreeParserCtxt(ctxt);
12342         return(-1);
12343     }
12344     newDoc->properties = XML_DOC_INTERNAL;
12345     if (ctx->myDoc->dict) {
12346         newDoc->dict = ctx->myDoc->dict;
12347         xmlDictReference(newDoc->dict);
12348     }
12349     if (ctx->myDoc != NULL) {
12350         newDoc->intSubset = ctx->myDoc->intSubset;
12351         newDoc->extSubset = ctx->myDoc->extSubset;
12352     }
12353     if (ctx->myDoc->URL != NULL) {
12354         newDoc->URL = xmlStrdup(ctx->myDoc->URL);
12355     }
12356     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12357     if (newRoot == NULL) {
12358         ctxt->sax = oldsax;
12359         xmlFreeParserCtxt(ctxt);
12360         newDoc->intSubset = NULL;
12361         newDoc->extSubset = NULL;
12362         xmlFreeDoc(newDoc);
12363         return(-1);
12364     }
12365     xmlAddChild((xmlNodePtr) newDoc, newRoot);
12366     nodePush(ctxt, newDoc->children);
12367     if (ctx->myDoc == NULL) {
12368         ctxt->myDoc = newDoc;
12369     } else {
12370         ctxt->myDoc = ctx->myDoc;
12371         newDoc->children->doc = ctx->myDoc;
12372     }
12373
12374     /*
12375      * Get the 4 first bytes and decode the charset
12376      * if enc != XML_CHAR_ENCODING_NONE
12377      * plug some encoding conversion routines.
12378      */
12379     GROW
12380     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12381         start[0] = RAW;
12382         start[1] = NXT(1);
12383         start[2] = NXT(2);
12384         start[3] = NXT(3);
12385         enc = xmlDetectCharEncoding(start, 4);
12386         if (enc != XML_CHAR_ENCODING_NONE) {
12387             xmlSwitchEncoding(ctxt, enc);
12388         }
12389     }
12390
12391     /*
12392      * Parse a possible text declaration first
12393      */
12394     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12395         xmlParseTextDecl(ctxt);
12396         /*
12397          * An XML-1.0 document can't reference an entity not XML-1.0
12398          */
12399         if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
12400             (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12401             xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, 
12402                            "Version mismatch between document and entity\n");
12403         }
12404     }
12405
12406     /*
12407      * Doing validity checking on chunk doesn't make sense
12408      */
12409     ctxt->instate = XML_PARSER_CONTENT;
12410     ctxt->validate = ctx->validate;
12411     ctxt->valid = ctx->valid;
12412     ctxt->loadsubset = ctx->loadsubset;
12413     ctxt->depth = ctx->depth + 1;
12414     ctxt->replaceEntities = ctx->replaceEntities;
12415     if (ctxt->validate) {
12416         ctxt->vctxt.error = ctx->vctxt.error;
12417         ctxt->vctxt.warning = ctx->vctxt.warning;
12418     } else {
12419         ctxt->vctxt.error = NULL;
12420         ctxt->vctxt.warning = NULL;
12421     }
12422     ctxt->vctxt.nodeTab = NULL;
12423     ctxt->vctxt.nodeNr = 0;
12424     ctxt->vctxt.nodeMax = 0;
12425     ctxt->vctxt.node = NULL;
12426     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12427     ctxt->dict = ctx->dict;
12428     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12429     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12430     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12431     ctxt->dictNames = ctx->dictNames;
12432     ctxt->attsDefault = ctx->attsDefault;
12433     ctxt->attsSpecial = ctx->attsSpecial;
12434     ctxt->linenumbers = ctx->linenumbers;
12435
12436     xmlParseContent(ctxt);
12437
12438     ctx->validate = ctxt->validate;
12439     ctx->valid = ctxt->valid;
12440     if ((RAW == '<') && (NXT(1) == '/')) {
12441         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12442     } else if (RAW != 0) {
12443         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12444     }
12445     if (ctxt->node != newDoc->children) {
12446         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12447     }
12448
12449     if (!ctxt->wellFormed) {
12450         if (ctxt->errNo == 0)
12451             ret = 1;
12452         else
12453             ret = ctxt->errNo;
12454     } else {
12455         if (lst != NULL) {
12456             xmlNodePtr cur;
12457
12458             /*
12459              * Return the newly created nodeset after unlinking it from
12460              * they pseudo parent.
12461              */
12462             cur = newDoc->children->children;
12463             *lst = cur;
12464             while (cur != NULL) {
12465                 cur->parent = NULL;
12466                 cur = cur->next;
12467             }
12468             newDoc->children->children = NULL;
12469         }
12470         ret = 0;
12471     }
12472     ctxt->sax = oldsax;
12473     ctxt->dict = NULL;
12474     ctxt->attsDefault = NULL;
12475     ctxt->attsSpecial = NULL;
12476     xmlFreeParserCtxt(ctxt);
12477     newDoc->intSubset = NULL;
12478     newDoc->extSubset = NULL;
12479     xmlFreeDoc(newDoc);
12480
12481     return(ret);
12482 }
12483
12484 /**
12485  * xmlParseExternalEntityPrivate:
12486  * @doc:  the document the chunk pertains to
12487  * @oldctxt:  the previous parser context if available
12488  * @sax:  the SAX handler bloc (possibly NULL)
12489  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12490  * @depth:  Used for loop detection, use 0
12491  * @URL:  the URL for the entity to load
12492  * @ID:  the System ID for the entity to load
12493  * @list:  the return value for the set of parsed nodes
12494  *
12495  * Private version of xmlParseExternalEntity()
12496  *
12497  * Returns 0 if the entity is well formed, -1 in case of args problem and
12498  *    the parser error code otherwise
12499  */
12500
12501 static xmlParserErrors
12502 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
12503                       xmlSAXHandlerPtr sax,
12504                       void *user_data, int depth, const xmlChar *URL,
12505                       const xmlChar *ID, xmlNodePtr *list) {
12506     xmlParserCtxtPtr ctxt;
12507     xmlDocPtr newDoc;
12508     xmlNodePtr newRoot;
12509     xmlSAXHandlerPtr oldsax = NULL;
12510     xmlParserErrors ret = XML_ERR_OK;
12511     xmlChar start[4];
12512     xmlCharEncoding enc;
12513
12514     if (((depth > 40) &&
12515         ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12516         (depth > 1024)) {
12517         return(XML_ERR_ENTITY_LOOP);
12518     }
12519
12520     if (list != NULL)
12521         *list = NULL;
12522     if ((URL == NULL) && (ID == NULL))
12523         return(XML_ERR_INTERNAL_ERROR);
12524     if (doc == NULL)
12525         return(XML_ERR_INTERNAL_ERROR);
12526
12527
12528     ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
12529     if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12530     ctxt->userData = ctxt;
12531     if (oldctxt != NULL) {
12532         ctxt->_private = oldctxt->_private;
12533         ctxt->loadsubset = oldctxt->loadsubset;
12534         ctxt->validate = oldctxt->validate;
12535         ctxt->external = oldctxt->external;
12536         ctxt->record_info = oldctxt->record_info;
12537         ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
12538         ctxt->node_seq.length = oldctxt->node_seq.length;
12539         ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
12540     } else {
12541         /*
12542          * Doing validity checking on chunk without context
12543          * doesn't make sense
12544          */
12545         ctxt->_private = NULL;
12546         ctxt->validate = 0;
12547         ctxt->external = 2;
12548         ctxt->loadsubset = 0;
12549     }
12550     if (sax != NULL) {
12551         oldsax = ctxt->sax;
12552         ctxt->sax = sax;
12553         if (user_data != NULL)
12554             ctxt->userData = user_data;
12555     }
12556     xmlDetectSAX2(ctxt);
12557     newDoc = xmlNewDoc(BAD_CAST "1.0");
12558     if (newDoc == NULL) {
12559         ctxt->node_seq.maximum = 0;
12560         ctxt->node_seq.length = 0;
12561         ctxt->node_seq.buffer = NULL;
12562         xmlFreeParserCtxt(ctxt);
12563         return(XML_ERR_INTERNAL_ERROR);
12564     }
12565     newDoc->properties = XML_DOC_INTERNAL;
12566     newDoc->intSubset = doc->intSubset;
12567     newDoc->extSubset = doc->extSubset;
12568     newDoc->dict = doc->dict;
12569     xmlDictReference(newDoc->dict);
12570
12571     if (doc->URL != NULL) {
12572         newDoc->URL = xmlStrdup(doc->URL);
12573     }
12574     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12575     if (newRoot == NULL) {
12576         if (sax != NULL)
12577             ctxt->sax = oldsax;
12578         ctxt->node_seq.maximum = 0;
12579         ctxt->node_seq.length = 0;
12580         ctxt->node_seq.buffer = NULL;
12581         xmlFreeParserCtxt(ctxt);
12582         newDoc->intSubset = NULL;
12583         newDoc->extSubset = NULL;
12584         xmlFreeDoc(newDoc);
12585         return(XML_ERR_INTERNAL_ERROR);
12586     }
12587     xmlAddChild((xmlNodePtr) newDoc, newRoot);
12588     nodePush(ctxt, newDoc->children);
12589     ctxt->myDoc = doc;
12590     newRoot->doc = doc;
12591
12592     /*
12593      * Get the 4 first bytes and decode the charset
12594      * if enc != XML_CHAR_ENCODING_NONE
12595      * plug some encoding conversion routines.
12596      */
12597     GROW;
12598     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12599         start[0] = RAW;
12600         start[1] = NXT(1);
12601         start[2] = NXT(2);
12602         start[3] = NXT(3);
12603         enc = xmlDetectCharEncoding(start, 4);
12604         if (enc != XML_CHAR_ENCODING_NONE) {
12605             xmlSwitchEncoding(ctxt, enc);
12606         }
12607     }
12608
12609     /*
12610      * Parse a possible text declaration first
12611      */
12612     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12613         xmlParseTextDecl(ctxt);
12614     }
12615
12616     ctxt->instate = XML_PARSER_CONTENT;
12617     ctxt->depth = depth;
12618
12619     xmlParseContent(ctxt);
12620
12621     if ((RAW == '<') && (NXT(1) == '/')) {
12622         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12623     } else if (RAW != 0) {
12624         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12625     }
12626     if (ctxt->node != newDoc->children) {
12627         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12628     }
12629
12630     if (!ctxt->wellFormed) {
12631         if (ctxt->errNo == 0)
12632             ret = XML_ERR_INTERNAL_ERROR;
12633         else
12634             ret = (xmlParserErrors)ctxt->errNo;
12635     } else {
12636         if (list != NULL) {
12637             xmlNodePtr cur;
12638
12639             /*
12640              * Return the newly created nodeset after unlinking it from
12641              * they pseudo parent.
12642              */
12643             cur = newDoc->children->children;
12644             *list = cur;
12645             while (cur != NULL) {
12646                 cur->parent = NULL;
12647                 cur = cur->next;
12648             }
12649             newDoc->children->children = NULL;
12650         }
12651         ret = XML_ERR_OK;
12652     }
12653
12654     /*
12655      * Record in the parent context the number of entities replacement
12656      * done when parsing that reference.
12657      */
12658     if (oldctxt != NULL)
12659         oldctxt->nbentities += ctxt->nbentities;
12660
12661     /*
12662      * Also record the size of the entity parsed
12663      */
12664     if (ctxt->input != NULL) {
12665         oldctxt->sizeentities += ctxt->input->consumed;
12666         oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
12667     }
12668     /*
12669      * And record the last error if any
12670      */
12671     if (ctxt->lastError.code != XML_ERR_OK)
12672         xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12673
12674     if (sax != NULL) 
12675         ctxt->sax = oldsax;
12676     oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
12677     oldctxt->node_seq.length = ctxt->node_seq.length;
12678     oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
12679     ctxt->node_seq.maximum = 0;
12680     ctxt->node_seq.length = 0;
12681     ctxt->node_seq.buffer = NULL;
12682     xmlFreeParserCtxt(ctxt);
12683     newDoc->intSubset = NULL;
12684     newDoc->extSubset = NULL;
12685     xmlFreeDoc(newDoc);
12686
12687     return(ret);
12688 }
12689
12690 #ifdef LIBXML_SAX1_ENABLED
12691 /**
12692  * xmlParseExternalEntity:
12693  * @doc:  the document the chunk pertains to
12694  * @sax:  the SAX handler bloc (possibly NULL)
12695  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12696  * @depth:  Used for loop detection, use 0
12697  * @URL:  the URL for the entity to load
12698  * @ID:  the System ID for the entity to load
12699  * @lst:  the return value for the set of parsed nodes
12700  *
12701  * Parse an external general entity
12702  * An external general parsed entity is well-formed if it matches the
12703  * production labeled extParsedEnt.
12704  *
12705  * [78] extParsedEnt ::= TextDecl? content
12706  *
12707  * Returns 0 if the entity is well formed, -1 in case of args problem and
12708  *    the parser error code otherwise
12709  */
12710
12711 int
12712 xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
12713           int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
12714     return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
12715                                        ID, lst));
12716 }
12717
12718 /**
12719  * xmlParseBalancedChunkMemory:
12720  * @doc:  the document the chunk pertains to
12721  * @sax:  the SAX handler bloc (possibly NULL)
12722  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12723  * @depth:  Used for loop detection, use 0
12724  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12725  * @lst:  the return value for the set of parsed nodes
12726  *
12727  * Parse a well-balanced chunk of an XML document
12728  * called by the parser
12729  * The allowed sequence for the Well Balanced Chunk is the one defined by
12730  * the content production in the XML grammar:
12731  *
12732  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12733  *
12734  * Returns 0 if the chunk is well balanced, -1 in case of args problem and
12735  *    the parser error code otherwise
12736  */
12737
12738 int
12739 xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12740      void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
12741     return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
12742                                                 depth, string, lst, 0 );
12743 }
12744 #endif /* LIBXML_SAX1_ENABLED */
12745
12746 /**
12747  * xmlParseBalancedChunkMemoryInternal:
12748  * @oldctxt:  the existing parsing context
12749  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12750  * @user_data:  the user data field for the parser context
12751  * @lst:  the return value for the set of parsed nodes
12752  *
12753  *
12754  * Parse a well-balanced chunk of an XML document
12755  * called by the parser
12756  * The allowed sequence for the Well Balanced Chunk is the one defined by
12757  * the content production in the XML grammar:
12758  *
12759  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12760  *
12761  * Returns XML_ERR_OK if the chunk is well balanced, and the parser
12762  * error code otherwise
12763  *
12764  * In case recover is set to 1, the nodelist will not be empty even if
12765  * the parsed chunk is not well balanced.
12766  */
12767 static xmlParserErrors
12768 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
12769         const xmlChar *string, void *user_data, xmlNodePtr *lst) {
12770     xmlParserCtxtPtr ctxt;
12771     xmlDocPtr newDoc = NULL;
12772     xmlNodePtr newRoot;
12773     xmlSAXHandlerPtr oldsax = NULL;
12774     xmlNodePtr content = NULL;
12775     xmlNodePtr last = NULL;
12776     int size;
12777     xmlParserErrors ret = XML_ERR_OK;
12778 #ifdef SAX2
12779     int i;
12780 #endif
12781
12782     if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12783         (oldctxt->depth >  1024)) {
12784         return(XML_ERR_ENTITY_LOOP);
12785     }
12786
12787
12788     if (lst != NULL)
12789         *lst = NULL;
12790     if (string == NULL)
12791         return(XML_ERR_INTERNAL_ERROR);
12792
12793     size = xmlStrlen(string);
12794
12795     ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
12796     if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12797     if (user_data != NULL)
12798         ctxt->userData = user_data;
12799     else
12800         ctxt->userData = ctxt;
12801     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12802     ctxt->dict = oldctxt->dict;
12803     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12804     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12805     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12806
12807 #ifdef SAX2
12808     /* propagate namespaces down the entity */
12809     for (i = 0;i < oldctxt->nsNr;i += 2) {
12810         nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
12811     }
12812 #endif
12813
12814     oldsax = ctxt->sax;
12815     ctxt->sax = oldctxt->sax;
12816     xmlDetectSAX2(ctxt);
12817     ctxt->replaceEntities = oldctxt->replaceEntities;
12818     ctxt->options = oldctxt->options;
12819
12820     ctxt->_private = oldctxt->_private;
12821     if (oldctxt->myDoc == NULL) {
12822         newDoc = xmlNewDoc(BAD_CAST "1.0");
12823         if (newDoc == NULL) {
12824             ctxt->sax = oldsax;
12825             ctxt->dict = NULL;
12826             xmlFreeParserCtxt(ctxt);
12827             return(XML_ERR_INTERNAL_ERROR);
12828         }
12829         newDoc->properties = XML_DOC_INTERNAL;
12830         newDoc->dict = ctxt->dict;
12831         xmlDictReference(newDoc->dict);
12832         ctxt->myDoc = newDoc;
12833     } else {
12834         ctxt->myDoc = oldctxt->myDoc;
12835         content = ctxt->myDoc->children;
12836         last = ctxt->myDoc->last;
12837     }
12838     newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
12839     if (newRoot == NULL) {
12840         ctxt->sax = oldsax;
12841         ctxt->dict = NULL;
12842         xmlFreeParserCtxt(ctxt);
12843         if (newDoc != NULL) {
12844             xmlFreeDoc(newDoc);
12845         }
12846         return(XML_ERR_INTERNAL_ERROR);
12847     }
12848     ctxt->myDoc->children = NULL;
12849     ctxt->myDoc->last = NULL;
12850     xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
12851     nodePush(ctxt, ctxt->myDoc->children);
12852     ctxt->instate = XML_PARSER_CONTENT;
12853     ctxt->depth = oldctxt->depth + 1;
12854
12855     ctxt->validate = 0;
12856     ctxt->loadsubset = oldctxt->loadsubset;
12857     if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
12858         /*
12859          * ID/IDREF registration will be done in xmlValidateElement below
12860          */
12861         ctxt->loadsubset |= XML_SKIP_IDS;
12862     }
12863     ctxt->dictNames = oldctxt->dictNames;
12864     ctxt->attsDefault = oldctxt->attsDefault;
12865     ctxt->attsSpecial = oldctxt->attsSpecial;
12866
12867     xmlParseContent(ctxt);
12868     if ((RAW == '<') && (NXT(1) == '/')) {
12869         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12870     } else if (RAW != 0) {
12871         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12872     }
12873     if (ctxt->node != ctxt->myDoc->children) {
12874         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12875     }
12876
12877     if (!ctxt->wellFormed) {
12878         if (ctxt->errNo == 0)
12879             ret = XML_ERR_INTERNAL_ERROR;
12880         else
12881             ret = (xmlParserErrors)ctxt->errNo;
12882     } else {
12883       ret = XML_ERR_OK;
12884     }
12885
12886     if ((lst != NULL) && (ret == XML_ERR_OK)) {
12887         xmlNodePtr cur;
12888
12889         /*
12890          * Return the newly created nodeset after unlinking it from
12891          * they pseudo parent.
12892          */
12893         cur = ctxt->myDoc->children->children;
12894         *lst = cur;
12895         while (cur != NULL) {
12896 #ifdef LIBXML_VALID_ENABLED
12897             if ((oldctxt->validate) && (oldctxt->wellFormed) &&
12898                 (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
12899                 (cur->type == XML_ELEMENT_NODE)) {
12900                 oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
12901                         oldctxt->myDoc, cur);
12902             }
12903 #endif /* LIBXML_VALID_ENABLED */
12904             cur->parent = NULL;
12905             cur = cur->next;
12906         }
12907         ctxt->myDoc->children->children = NULL;
12908     }
12909     if (ctxt->myDoc != NULL) {
12910         xmlFreeNode(ctxt->myDoc->children);
12911         ctxt->myDoc->children = content;
12912         ctxt->myDoc->last = last;
12913     }
12914
12915     /*
12916      * Record in the parent context the number of entities replacement
12917      * done when parsing that reference.
12918      */
12919     if (oldctxt != NULL)
12920         oldctxt->nbentities += ctxt->nbentities;
12921
12922     /*
12923      * Also record the last error if any
12924      */
12925     if (ctxt->lastError.code != XML_ERR_OK)
12926         xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12927
12928     ctxt->sax = oldsax;
12929     ctxt->dict = NULL;
12930     ctxt->attsDefault = NULL;
12931     ctxt->attsSpecial = NULL;
12932     xmlFreeParserCtxt(ctxt);
12933     if (newDoc != NULL) {
12934         xmlFreeDoc(newDoc);
12935     }
12936
12937     return(ret);
12938 }
12939
12940 /**
12941  * xmlParseInNodeContext:
12942  * @node:  the context node
12943  * @data:  the input string
12944  * @datalen:  the input string length in bytes
12945  * @options:  a combination of xmlParserOption
12946  * @lst:  the return value for the set of parsed nodes
12947  *
12948  * Parse a well-balanced chunk of an XML document
12949  * within the context (DTD, namespaces, etc ...) of the given node.
12950  *
12951  * The allowed sequence for the data is a Well Balanced Chunk defined by
12952  * the content production in the XML grammar:
12953  *
12954  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12955  *
12956  * Returns XML_ERR_OK if the chunk is well balanced, and the parser
12957  * error code otherwise
12958  */
12959 xmlParserErrors
12960 xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
12961                       int options, xmlNodePtr *lst) {
12962 #ifdef SAX2
12963     xmlParserCtxtPtr ctxt;
12964     xmlDocPtr doc = NULL;
12965     xmlNodePtr fake, cur;
12966     int nsnr = 0;
12967
12968     xmlParserErrors ret = XML_ERR_OK;
12969
12970     /*
12971      * check all input parameters, grab the document
12972      */
12973     if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
12974         return(XML_ERR_INTERNAL_ERROR);
12975     switch (node->type) {
12976         case XML_ELEMENT_NODE:
12977         case XML_ATTRIBUTE_NODE:
12978         case XML_TEXT_NODE:
12979         case XML_CDATA_SECTION_NODE:
12980         case XML_ENTITY_REF_NODE:
12981         case XML_PI_NODE:
12982         case XML_COMMENT_NODE:
12983         case XML_DOCUMENT_NODE:
12984         case XML_HTML_DOCUMENT_NODE:
12985             break;
12986         default:
12987             return(XML_ERR_INTERNAL_ERROR);
12988
12989     }
12990     while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
12991            (node->type != XML_DOCUMENT_NODE) &&
12992            (node->type != XML_HTML_DOCUMENT_NODE))
12993         node = node->parent;
12994     if (node == NULL)
12995         return(XML_ERR_INTERNAL_ERROR);
12996     if (node->type == XML_ELEMENT_NODE)
12997         doc = node->doc;
12998     else
12999         doc = (xmlDocPtr) node;
13000     if (doc == NULL)
13001         return(XML_ERR_INTERNAL_ERROR);
13002
13003     /*
13004      * allocate a context and set-up everything not related to the
13005      * node position in the tree
13006      */
13007     if (doc->type == XML_DOCUMENT_NODE)
13008         ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13009 #ifdef LIBXML_HTML_ENABLED
13010     else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13011         ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13012         /*
13013          * When parsing in context, it makes no sense to add implied
13014          * elements like html/body/etc...
13015          */
13016         options |= HTML_PARSE_NOIMPLIED;
13017     }
13018 #endif
13019     else
13020         return(XML_ERR_INTERNAL_ERROR);
13021
13022     if (ctxt == NULL)
13023         return(XML_ERR_NO_MEMORY);
13024
13025     /*
13026      * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13027      * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13028      * we must wait until the last moment to free the original one.
13029      */
13030     if (doc->dict != NULL) {
13031         if (ctxt->dict != NULL)
13032             xmlDictFree(ctxt->dict);
13033         ctxt->dict = doc->dict;
13034     } else
13035         options |= XML_PARSE_NODICT;
13036
13037     if (doc->encoding != NULL) {
13038         xmlCharEncodingHandlerPtr hdlr;
13039
13040         if (ctxt->encoding != NULL)
13041             xmlFree((xmlChar *) ctxt->encoding);
13042         ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13043
13044         hdlr = xmlFindCharEncodingHandler(doc->encoding);
13045         if (hdlr != NULL) {
13046             xmlSwitchToEncoding(ctxt, hdlr);
13047         } else {
13048             return(XML_ERR_UNSUPPORTED_ENCODING);
13049         }
13050     }
13051
13052     xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13053     xmlDetectSAX2(ctxt);
13054     ctxt->myDoc = doc;
13055
13056     fake = xmlNewComment(NULL);
13057     if (fake == NULL) {
13058         xmlFreeParserCtxt(ctxt);
13059         return(XML_ERR_NO_MEMORY);
13060     }
13061     xmlAddChild(node, fake);
13062
13063     if (node->type == XML_ELEMENT_NODE) {
13064         nodePush(ctxt, node);
13065         /*
13066          * initialize the SAX2 namespaces stack
13067          */
13068         cur = node;
13069         while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13070             xmlNsPtr ns = cur->nsDef;
13071             const xmlChar *iprefix, *ihref;
13072
13073             while (ns != NULL) {
13074                 if (ctxt->dict) {
13075                     iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13076                     ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13077                 } else {
13078                     iprefix = ns->prefix;
13079                     ihref = ns->href;
13080                 }
13081
13082                 if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13083                     nsPush(ctxt, iprefix, ihref);
13084                     nsnr++;
13085                 }
13086                 ns = ns->next;
13087             }
13088             cur = cur->parent;
13089         }
13090         ctxt->instate = XML_PARSER_CONTENT;
13091     }
13092
13093     if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13094         /*
13095          * ID/IDREF registration will be done in xmlValidateElement below
13096          */
13097         ctxt->loadsubset |= XML_SKIP_IDS;
13098     }
13099
13100 #ifdef LIBXML_HTML_ENABLED
13101     if (doc->type == XML_HTML_DOCUMENT_NODE)
13102         __htmlParseContent(ctxt);
13103     else
13104 #endif
13105         xmlParseContent(ctxt);
13106
13107     nsPop(ctxt, nsnr);
13108     if ((RAW == '<') && (NXT(1) == '/')) {
13109         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13110     } else if (RAW != 0) {
13111         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13112     }
13113     if ((ctxt->node != NULL) && (ctxt->node != node)) {
13114         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13115         ctxt->wellFormed = 0;
13116     }
13117
13118     if (!ctxt->wellFormed) {
13119         if (ctxt->errNo == 0)
13120             ret = XML_ERR_INTERNAL_ERROR;
13121         else
13122             ret = (xmlParserErrors)ctxt->errNo;
13123     } else {
13124         ret = XML_ERR_OK;
13125     }
13126
13127     /*
13128      * Return the newly created nodeset after unlinking it from
13129      * the pseudo sibling.
13130      */
13131
13132     cur = fake->next;
13133     fake->next = NULL;
13134     node->last = fake;
13135
13136     if (cur != NULL) {
13137         cur->prev = NULL;
13138     }
13139
13140     *lst = cur;
13141
13142     while (cur != NULL) {
13143         cur->parent = NULL;
13144         cur = cur->next;
13145     }
13146
13147     xmlUnlinkNode(fake);
13148     xmlFreeNode(fake);
13149
13150
13151     if (ret != XML_ERR_OK) {
13152         xmlFreeNodeList(*lst);
13153         *lst = NULL;
13154     }
13155
13156     if (doc->dict != NULL)
13157         ctxt->dict = NULL;
13158     xmlFreeParserCtxt(ctxt);
13159
13160     return(ret);
13161 #else /* !SAX2 */
13162     return(XML_ERR_INTERNAL_ERROR);
13163 #endif
13164 }
13165
13166 #ifdef LIBXML_SAX1_ENABLED
13167 /**
13168  * xmlParseBalancedChunkMemoryRecover:
13169  * @doc:  the document the chunk pertains to
13170  * @sax:  the SAX handler bloc (possibly NULL)
13171  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13172  * @depth:  Used for loop detection, use 0
13173  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13174  * @lst:  the return value for the set of parsed nodes
13175  * @recover: return nodes even if the data is broken (use 0)
13176  *
13177  *
13178  * Parse a well-balanced chunk of an XML document
13179  * called by the parser
13180  * The allowed sequence for the Well Balanced Chunk is the one defined by
13181  * the content production in the XML grammar:
13182  *
13183  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13184  *
13185  * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13186  *    the parser error code otherwise
13187  *
13188  * In case recover is set to 1, the nodelist will not be empty even if
13189  * the parsed chunk is not well balanced, assuming the parsing succeeded to
13190  * some extent.
13191  */
13192 int
13193 xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13194      void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13195      int recover) {
13196     xmlParserCtxtPtr ctxt;
13197     xmlDocPtr newDoc;
13198     xmlSAXHandlerPtr oldsax = NULL;
13199     xmlNodePtr content, newRoot;
13200     int size;
13201     int ret = 0;
13202
13203     if (depth > 40) {
13204         return(XML_ERR_ENTITY_LOOP);
13205     }
13206
13207
13208     if (lst != NULL)
13209         *lst = NULL;
13210     if (string == NULL)
13211         return(-1);
13212
13213     size = xmlStrlen(string);
13214
13215     ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13216     if (ctxt == NULL) return(-1);
13217     ctxt->userData = ctxt;
13218     if (sax != NULL) {
13219         oldsax = ctxt->sax;
13220         ctxt->sax = sax;
13221         if (user_data != NULL)
13222             ctxt->userData = user_data;
13223     }
13224     newDoc = xmlNewDoc(BAD_CAST "1.0");
13225     if (newDoc == NULL) {
13226         xmlFreeParserCtxt(ctxt);
13227         return(-1);
13228     }
13229     newDoc->properties = XML_DOC_INTERNAL;
13230     if ((doc != NULL) && (doc->dict != NULL)) {
13231         xmlDictFree(ctxt->dict);
13232         ctxt->dict = doc->dict;
13233         xmlDictReference(ctxt->dict);
13234         ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13235         ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13236         ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13237         ctxt->dictNames = 1;
13238     } else {
13239         xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13240     }
13241     if (doc != NULL) {
13242         newDoc->intSubset = doc->intSubset;
13243         newDoc->extSubset = doc->extSubset;
13244     }
13245     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13246     if (newRoot == NULL) {
13247         if (sax != NULL)
13248             ctxt->sax = oldsax;
13249         xmlFreeParserCtxt(ctxt);
13250         newDoc->intSubset = NULL;
13251         newDoc->extSubset = NULL;
13252         xmlFreeDoc(newDoc);
13253         return(-1);
13254     }
13255     xmlAddChild((xmlNodePtr) newDoc, newRoot);
13256     nodePush(ctxt, newRoot);
13257     if (doc == NULL) {
13258         ctxt->myDoc = newDoc;
13259     } else {
13260         ctxt->myDoc = newDoc;
13261         newDoc->children->doc = doc;
13262         /* Ensure that doc has XML spec namespace */
13263         xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13264         newDoc->oldNs = doc->oldNs;
13265     }
13266     ctxt->instate = XML_PARSER_CONTENT;
13267     ctxt->depth = depth;
13268
13269     /*
13270      * Doing validity checking on chunk doesn't make sense
13271      */
13272     ctxt->validate = 0;
13273     ctxt->loadsubset = 0;
13274     xmlDetectSAX2(ctxt);
13275
13276     if ( doc != NULL ){
13277         content = doc->children;
13278         doc->children = NULL;
13279         xmlParseContent(ctxt);
13280         doc->children = content;
13281     }
13282     else {
13283         xmlParseContent(ctxt);
13284     }
13285     if ((RAW == '<') && (NXT(1) == '/')) {
13286         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13287     } else if (RAW != 0) {
13288         xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13289     }
13290     if (ctxt->node != newDoc->children) {
13291         xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13292     }
13293
13294     if (!ctxt->wellFormed) {
13295         if (ctxt->errNo == 0)
13296             ret = 1;
13297         else
13298             ret = ctxt->errNo;
13299     } else {
13300       ret = 0;
13301     }
13302
13303     if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13304         xmlNodePtr cur;
13305
13306         /*
13307          * Return the newly created nodeset after unlinking it from
13308          * they pseudo parent.
13309          */
13310         cur = newDoc->children->children;
13311         *lst = cur;
13312         while (cur != NULL) {
13313             xmlSetTreeDoc(cur, doc);
13314             cur->parent = NULL;
13315             cur = cur->next;
13316         }
13317         newDoc->children->children = NULL;
13318     }
13319
13320     if (sax != NULL)
13321         ctxt->sax = oldsax;
13322     xmlFreeParserCtxt(ctxt);
13323     newDoc->intSubset = NULL;
13324     newDoc->extSubset = NULL;
13325     newDoc->oldNs = NULL;
13326     xmlFreeDoc(newDoc);
13327
13328     return(ret);
13329 }
13330
13331 /**
13332  * xmlSAXParseEntity:
13333  * @sax:  the SAX handler block
13334  * @filename:  the filename
13335  *
13336  * parse an XML external entity out of context and build a tree.
13337  * It use the given SAX function block to handle the parsing callback.
13338  * If sax is NULL, fallback to the default DOM tree building routines.
13339  *
13340  * [78] extParsedEnt ::= TextDecl? content
13341  *
13342  * This correspond to a "Well Balanced" chunk
13343  *
13344  * Returns the resulting document tree
13345  */
13346
13347 xmlDocPtr
13348 xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13349     xmlDocPtr ret;
13350     xmlParserCtxtPtr ctxt;
13351
13352     ctxt = xmlCreateFileParserCtxt(filename);
13353     if (ctxt == NULL) {
13354         return(NULL);
13355     }
13356     if (sax != NULL) {
13357         if (ctxt->sax != NULL)
13358             xmlFree(ctxt->sax);
13359         ctxt->sax = sax;
13360         ctxt->userData = NULL;
13361     }
13362
13363     xmlParseExtParsedEnt(ctxt);
13364
13365     if (ctxt->wellFormed)
13366         ret = ctxt->myDoc;
13367     else {
13368         ret = NULL;
13369         xmlFreeDoc(ctxt->myDoc);
13370         ctxt->myDoc = NULL;
13371     }
13372     if (sax != NULL)
13373         ctxt->sax = NULL;
13374     xmlFreeParserCtxt(ctxt);
13375
13376     return(ret);
13377 }
13378
13379 /**
13380  * xmlParseEntity:
13381  * @filename:  the filename
13382  *
13383  * parse an XML external entity out of context and build a tree.
13384  *
13385  * [78] extParsedEnt ::= TextDecl? content
13386  *
13387  * This correspond to a "Well Balanced" chunk
13388  *
13389  * Returns the resulting document tree
13390  */
13391
13392 xmlDocPtr
13393 xmlParseEntity(const char *filename) {
13394     return(xmlSAXParseEntity(NULL, filename));
13395 }
13396 #endif /* LIBXML_SAX1_ENABLED */
13397
13398 /**
13399  * xmlCreateEntityParserCtxtInternal:
13400  * @URL:  the entity URL
13401  * @ID:  the entity PUBLIC ID
13402  * @base:  a possible base for the target URI
13403  * @pctx:  parser context used to set options on new context
13404  *
13405  * Create a parser context for an external entity
13406  * Automatic support for ZLIB/Compress compressed document is provided
13407  * by default if found at compile-time.
13408  *
13409  * Returns the new parser context or NULL
13410  */
13411 static xmlParserCtxtPtr
13412 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
13413                           const xmlChar *base, xmlParserCtxtPtr pctx) {
13414     xmlParserCtxtPtr ctxt;
13415     xmlParserInputPtr inputStream;
13416     char *directory = NULL;
13417     xmlChar *uri;
13418
13419     ctxt = xmlNewParserCtxt();
13420     if (ctxt == NULL) {
13421         return(NULL);
13422     }
13423
13424     if (pctx != NULL) {
13425         ctxt->options = pctx->options;
13426         ctxt->_private = pctx->_private;
13427     }
13428
13429     uri = xmlBuildURI(URL, base);
13430
13431     if (uri == NULL) {
13432         inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13433         if (inputStream == NULL) {
13434             xmlFreeParserCtxt(ctxt);
13435             return(NULL);
13436         }
13437
13438         inputPush(ctxt, inputStream);
13439
13440         if ((ctxt->directory == NULL) && (directory == NULL))
13441             directory = xmlParserGetDirectory((char *)URL);
13442         if ((ctxt->directory == NULL) && (directory != NULL))
13443             ctxt->directory = directory;
13444     } else {
13445         inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
13446         if (inputStream == NULL) {
13447             xmlFree(uri);
13448             xmlFreeParserCtxt(ctxt);
13449             return(NULL);
13450         }
13451
13452         inputPush(ctxt, inputStream);
13453
13454         if ((ctxt->directory == NULL) && (directory == NULL))
13455             directory = xmlParserGetDirectory((char *)uri);
13456         if ((ctxt->directory == NULL) && (directory != NULL))
13457             ctxt->directory = directory;
13458         xmlFree(uri);
13459     }
13460     return(ctxt);
13461 }
13462
13463 /**
13464  * xmlCreateEntityParserCtxt:
13465  * @URL:  the entity URL
13466  * @ID:  the entity PUBLIC ID
13467  * @base:  a possible base for the target URI
13468  *
13469  * Create a parser context for an external entity
13470  * Automatic support for ZLIB/Compress compressed document is provided
13471  * by default if found at compile-time.
13472  *
13473  * Returns the new parser context or NULL
13474  */
13475 xmlParserCtxtPtr
13476 xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
13477                           const xmlChar *base) {
13478     return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
13479
13480 }
13481
13482 /************************************************************************
13483  *                                                                      *
13484  *              Front ends when parsing from a file                     *
13485  *                                                                      *
13486  ************************************************************************/
13487
13488 /**
13489  * xmlCreateURLParserCtxt:
13490  * @filename:  the filename or URL
13491  * @options:  a combination of xmlParserOption
13492  *
13493  * Create a parser context for a file or URL content. 
13494  * Automatic support for ZLIB/Compress compressed document is provided
13495  * by default if found at compile-time and for file accesses
13496  *
13497  * Returns the new parser context or NULL
13498  */
13499 xmlParserCtxtPtr
13500 xmlCreateURLParserCtxt(const char *filename, int options)
13501 {
13502     xmlParserCtxtPtr ctxt;
13503     xmlParserInputPtr inputStream;
13504     char *directory = NULL;
13505
13506     ctxt = xmlNewParserCtxt();
13507     if (ctxt == NULL) {
13508         xmlErrMemory(NULL, "cannot allocate parser context");
13509         return(NULL);
13510     }
13511
13512     if (options)
13513         xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13514     ctxt->linenumbers = 1;
13515
13516     inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
13517     if (inputStream == NULL) {
13518         xmlFreeParserCtxt(ctxt);
13519         return(NULL);
13520     }
13521
13522     inputPush(ctxt, inputStream);
13523     if ((ctxt->directory == NULL) && (directory == NULL))
13524         directory = xmlParserGetDirectory(filename);
13525     if ((ctxt->directory == NULL) && (directory != NULL))
13526         ctxt->directory = directory;
13527
13528     return(ctxt);
13529 }
13530
13531 /**
13532  * xmlCreateFileParserCtxt:
13533  * @filename:  the filename
13534  *
13535  * Create a parser context for a file content. 
13536  * Automatic support for ZLIB/Compress compressed document is provided
13537  * by default if found at compile-time.
13538  *
13539  * Returns the new parser context or NULL
13540  */
13541 xmlParserCtxtPtr
13542 xmlCreateFileParserCtxt(const char *filename)
13543 {
13544     return(xmlCreateURLParserCtxt(filename, 0));
13545 }
13546
13547 #ifdef LIBXML_SAX1_ENABLED
13548 /**
13549  * xmlSAXParseFileWithData:
13550  * @sax:  the SAX handler block
13551  * @filename:  the filename
13552  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13553  *             documents
13554  * @data:  the userdata
13555  *
13556  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13557  * compressed document is provided by default if found at compile-time.
13558  * It use the given SAX function block to handle the parsing callback.
13559  * If sax is NULL, fallback to the default DOM tree building routines.
13560  *
13561  * User data (void *) is stored within the parser context in the
13562  * context's _private member, so it is available nearly everywhere in libxml
13563  *
13564  * Returns the resulting document tree
13565  */
13566
13567 xmlDocPtr
13568 xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
13569                         int recovery, void *data) {
13570     xmlDocPtr ret;
13571     xmlParserCtxtPtr ctxt;
13572
13573     xmlInitParser();
13574
13575     ctxt = xmlCreateFileParserCtxt(filename);
13576     if (ctxt == NULL) {
13577         return(NULL);
13578     }
13579     if (sax != NULL) {
13580         if (ctxt->sax != NULL)
13581             xmlFree(ctxt->sax);
13582         ctxt->sax = sax;
13583     }
13584     xmlDetectSAX2(ctxt);
13585     if (data!=NULL) {
13586         ctxt->_private = data;
13587     }
13588
13589     if (ctxt->directory == NULL)
13590         ctxt->directory = xmlParserGetDirectory(filename);
13591
13592     ctxt->recovery = recovery;
13593
13594     xmlParseDocument(ctxt);
13595
13596     if ((ctxt->wellFormed) || recovery) {
13597         ret = ctxt->myDoc;
13598         if (ret != NULL) {
13599             if (ctxt->input->buf->compressed > 0)
13600                 ret->compression = 9;
13601             else
13602                 ret->compression = ctxt->input->buf->compressed;
13603         }
13604     }
13605     else {
13606        ret = NULL;
13607        xmlFreeDoc(ctxt->myDoc);
13608        ctxt->myDoc = NULL;
13609     }
13610     if (sax != NULL)
13611         ctxt->sax = NULL;
13612     xmlFreeParserCtxt(ctxt);
13613     
13614     return(ret);
13615 }
13616
13617 /**
13618  * xmlSAXParseFile:
13619  * @sax:  the SAX handler block
13620  * @filename:  the filename
13621  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13622  *             documents
13623  *
13624  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13625  * compressed document is provided by default if found at compile-time.
13626  * It use the given SAX function block to handle the parsing callback.
13627  * If sax is NULL, fallback to the default DOM tree building routines.
13628  *
13629  * Returns the resulting document tree
13630  */
13631
13632 xmlDocPtr
13633 xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
13634                           int recovery) {
13635     return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
13636 }
13637
13638 /**
13639  * xmlRecoverDoc:
13640  * @cur:  a pointer to an array of xmlChar
13641  *
13642  * parse an XML in-memory document and build a tree.
13643  * In the case the document is not Well Formed, a attempt to build a
13644  * tree is tried anyway
13645  *
13646  * Returns the resulting document tree or NULL in case of failure
13647  */
13648
13649 xmlDocPtr
13650 xmlRecoverDoc(const xmlChar *cur) {
13651     return(xmlSAXParseDoc(NULL, cur, 1));
13652 }
13653
13654 /**
13655  * xmlParseFile:
13656  * @filename:  the filename
13657  *
13658  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13659  * compressed document is provided by default if found at compile-time.
13660  *
13661  * Returns the resulting document tree if the file was wellformed,
13662  * NULL otherwise.
13663  */
13664
13665 xmlDocPtr
13666 xmlParseFile(const char *filename) {
13667     return(xmlSAXParseFile(NULL, filename, 0));
13668 }
13669
13670 /**
13671  * xmlRecoverFile:
13672  * @filename:  the filename
13673  *
13674  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13675  * compressed document is provided by default if found at compile-time.
13676  * In the case the document is not Well Formed, it attempts to build
13677  * a tree anyway
13678  *
13679  * Returns the resulting document tree or NULL in case of failure
13680  */
13681
13682 xmlDocPtr
13683 xmlRecoverFile(const char *filename) {
13684     return(xmlSAXParseFile(NULL, filename, 1));
13685 }
13686
13687
13688 /**
13689  * xmlSetupParserForBuffer:
13690  * @ctxt:  an XML parser context
13691  * @buffer:  a xmlChar * buffer
13692  * @filename:  a file name
13693  *
13694  * Setup the parser context to parse a new buffer; Clears any prior
13695  * contents from the parser context. The buffer parameter must not be
13696  * NULL, but the filename parameter can be
13697  */
13698 void
13699 xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
13700                              const char* filename)
13701 {
13702     xmlParserInputPtr input;
13703
13704     if ((ctxt == NULL) || (buffer == NULL))
13705         return;
13706
13707     input = xmlNewInputStream(ctxt);
13708     if (input == NULL) {
13709         xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
13710         xmlClearParserCtxt(ctxt);
13711         return;
13712     }
13713   
13714     xmlClearParserCtxt(ctxt);
13715     if (filename != NULL)
13716         input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
13717     input->base = buffer;
13718     input->cur = buffer;
13719     input->end = &buffer[xmlStrlen(buffer)];
13720     inputPush(ctxt, input);
13721 }
13722
13723 /**
13724  * xmlSAXUserParseFile:
13725  * @sax:  a SAX handler
13726  * @user_data:  The user data returned on SAX callbacks
13727  * @filename:  a file name
13728  *
13729  * parse an XML file and call the given SAX handler routines.
13730  * Automatic support for ZLIB/Compress compressed document is provided
13731  * 
13732  * Returns 0 in case of success or a error number otherwise
13733  */
13734 int
13735 xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
13736                     const char *filename) {
13737     int ret = 0;
13738     xmlParserCtxtPtr ctxt;
13739     
13740     ctxt = xmlCreateFileParserCtxt(filename);
13741     if (ctxt == NULL) return -1;
13742     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
13743         xmlFree(ctxt->sax);
13744     ctxt->sax = sax;
13745     xmlDetectSAX2(ctxt);
13746
13747     if (user_data != NULL)
13748         ctxt->userData = user_data;
13749     
13750     xmlParseDocument(ctxt);
13751     
13752     if (ctxt->wellFormed)
13753         ret = 0;
13754     else {
13755         if (ctxt->errNo != 0)
13756             ret = ctxt->errNo;
13757         else
13758             ret = -1;
13759     }
13760     if (sax != NULL)
13761         ctxt->sax = NULL;
13762     if (ctxt->myDoc != NULL) {
13763         xmlFreeDoc(ctxt->myDoc);
13764         ctxt->myDoc = NULL;
13765     }
13766     xmlFreeParserCtxt(ctxt);
13767     
13768     return ret;
13769 }
13770 #endif /* LIBXML_SAX1_ENABLED */
13771
13772 /************************************************************************
13773  *                                                                      *
13774  *              Front ends when parsing from memory                     *
13775  *                                                                      *
13776  ************************************************************************/
13777
13778 /**
13779  * xmlCreateMemoryParserCtxt:
13780  * @buffer:  a pointer to a char array
13781  * @size:  the size of the array
13782  *
13783  * Create a parser context for an XML in-memory document.
13784  *
13785  * Returns the new parser context or NULL
13786  */
13787 xmlParserCtxtPtr
13788 xmlCreateMemoryParserCtxt(const char *buffer, int size) {
13789     xmlParserCtxtPtr ctxt;
13790     xmlParserInputPtr input;
13791     xmlParserInputBufferPtr buf;
13792
13793     if (buffer == NULL)
13794         return(NULL);
13795     if (size <= 0)
13796         return(NULL);
13797
13798     ctxt = xmlNewParserCtxt();
13799     if (ctxt == NULL)
13800         return(NULL);
13801
13802     /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
13803     buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
13804     if (buf == NULL) {
13805         xmlFreeParserCtxt(ctxt);
13806         return(NULL);
13807     }
13808
13809     input = xmlNewInputStream(ctxt);
13810     if (input == NULL) {
13811         xmlFreeParserInputBuffer(buf);
13812         xmlFreeParserCtxt(ctxt);
13813         return(NULL);
13814     }
13815
13816     input->filename = NULL;
13817     input->buf = buf;
13818     input->base = input->buf->buffer->content;
13819     input->cur = input->buf->buffer->content;
13820     input->end = &input->buf->buffer->content[input->buf->buffer->use];
13821
13822     inputPush(ctxt, input);
13823     return(ctxt);
13824 }
13825
13826 #ifdef LIBXML_SAX1_ENABLED
13827 /**
13828  * xmlSAXParseMemoryWithData:
13829  * @sax:  the SAX handler block
13830  * @buffer:  an pointer to a char array
13831  * @size:  the size of the array
13832  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13833  *             documents
13834  * @data:  the userdata
13835  *
13836  * parse an XML in-memory block and use the given SAX function block
13837  * to handle the parsing callback. If sax is NULL, fallback to the default
13838  * DOM tree building routines.
13839  *
13840  * User data (void *) is stored within the parser context in the
13841  * context's _private member, so it is available nearly everywhere in libxml
13842  *
13843  * Returns the resulting document tree
13844  */
13845
13846 xmlDocPtr
13847 xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
13848                   int size, int recovery, void *data) {
13849     xmlDocPtr ret;
13850     xmlParserCtxtPtr ctxt;
13851
13852     xmlInitParser();
13853
13854     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
13855     if (ctxt == NULL) return(NULL);
13856     if (sax != NULL) {
13857         if (ctxt->sax != NULL)
13858             xmlFree(ctxt->sax);
13859         ctxt->sax = sax;
13860     }
13861     xmlDetectSAX2(ctxt);
13862     if (data!=NULL) {
13863         ctxt->_private=data;
13864     }
13865
13866     ctxt->recovery = recovery;
13867
13868     xmlParseDocument(ctxt);
13869
13870     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
13871     else {
13872        ret = NULL;
13873        xmlFreeDoc(ctxt->myDoc);
13874        ctxt->myDoc = NULL;
13875     }
13876     if (sax != NULL) 
13877         ctxt->sax = NULL;
13878     xmlFreeParserCtxt(ctxt);
13879
13880     return(ret);
13881 }
13882
13883 /**
13884  * xmlSAXParseMemory:
13885  * @sax:  the SAX handler block
13886  * @buffer:  an pointer to a char array
13887  * @size:  the size of the array
13888  * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
13889  *             documents
13890  *
13891  * parse an XML in-memory block and use the given SAX function block
13892  * to handle the parsing callback. If sax is NULL, fallback to the default
13893  * DOM tree building routines.
13894  * 
13895  * Returns the resulting document tree
13896  */
13897 xmlDocPtr
13898 xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
13899                   int size, int recovery) {
13900     return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
13901 }
13902
13903 /**
13904  * xmlParseMemory:
13905  * @buffer:  an pointer to a char array
13906  * @size:  the size of the array
13907  *
13908  * parse an XML in-memory block and build a tree.
13909  * 
13910  * Returns the resulting document tree
13911  */
13912
13913 xmlDocPtr xmlParseMemory(const char *buffer, int size) {
13914    return(xmlSAXParseMemory(NULL, buffer, size, 0));
13915 }
13916
13917 /**
13918  * xmlRecoverMemory:
13919  * @buffer:  an pointer to a char array
13920  * @size:  the size of the array
13921  *
13922  * parse an XML in-memory block and build a tree.
13923  * In the case the document is not Well Formed, an attempt to
13924  * build a tree is tried anyway
13925  *
13926  * Returns the resulting document tree or NULL in case of error
13927  */
13928
13929 xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
13930    return(xmlSAXParseMemory(NULL, buffer, size, 1));
13931 }
13932
13933 /**
13934  * xmlSAXUserParseMemory:
13935  * @sax:  a SAX handler
13936  * @user_data:  The user data returned on SAX callbacks
13937  * @buffer:  an in-memory XML document input
13938  * @size:  the length of the XML document in bytes
13939  *
13940  * A better SAX parsing routine.
13941  * parse an XML in-memory buffer and call the given SAX handler routines.
13942  *
13943  * Returns 0 in case of success or a error number otherwise
13944  */
13945 int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
13946                           const char *buffer, int size) {
13947     int ret = 0;
13948     xmlParserCtxtPtr ctxt;
13949
13950     xmlInitParser();
13951
13952     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
13953     if (ctxt == NULL) return -1;
13954     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
13955         xmlFree(ctxt->sax);
13956     ctxt->sax = sax;
13957     xmlDetectSAX2(ctxt);
13958
13959     if (user_data != NULL)
13960         ctxt->userData = user_data;
13961
13962     xmlParseDocument(ctxt);
13963     
13964     if (ctxt->wellFormed)
13965         ret = 0;
13966     else {
13967         if (ctxt->errNo != 0)
13968             ret = ctxt->errNo;
13969         else
13970             ret = -1;
13971     }
13972     if (sax != NULL)
13973         ctxt->sax = NULL;
13974     if (ctxt->myDoc != NULL) {
13975         xmlFreeDoc(ctxt->myDoc);
13976         ctxt->myDoc = NULL;
13977     }
13978     xmlFreeParserCtxt(ctxt);
13979     
13980     return ret;
13981 }
13982 #endif /* LIBXML_SAX1_ENABLED */
13983
13984 /**
13985  * xmlCreateDocParserCtxt:
13986  * @cur:  a pointer to an array of xmlChar
13987  *
13988  * Creates a parser context for an XML in-memory document.
13989  *
13990  * Returns the new parser context or NULL
13991  */
13992 xmlParserCtxtPtr
13993 xmlCreateDocParserCtxt(const xmlChar *cur) {
13994     int len;
13995
13996     if (cur == NULL)
13997         return(NULL);
13998     len = xmlStrlen(cur);
13999     return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14000 }
14001
14002 #ifdef LIBXML_SAX1_ENABLED
14003 /**
14004  * xmlSAXParseDoc:
14005  * @sax:  the SAX handler block
14006  * @cur:  a pointer to an array of xmlChar
14007  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14008  *             documents
14009  *
14010  * parse an XML in-memory document and build a tree.
14011  * It use the given SAX function block to handle the parsing callback.
14012  * If sax is NULL, fallback to the default DOM tree building routines.
14013  * 
14014  * Returns the resulting document tree
14015  */
14016
14017 xmlDocPtr
14018 xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14019     xmlDocPtr ret;
14020     xmlParserCtxtPtr ctxt;
14021     xmlSAXHandlerPtr oldsax = NULL;
14022
14023     if (cur == NULL) return(NULL);
14024
14025
14026     ctxt = xmlCreateDocParserCtxt(cur);
14027     if (ctxt == NULL) return(NULL);
14028     if (sax != NULL) { 
14029         oldsax = ctxt->sax;
14030         ctxt->sax = sax;
14031         ctxt->userData = NULL;
14032     }
14033     xmlDetectSAX2(ctxt);
14034
14035     xmlParseDocument(ctxt);
14036     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14037     else {
14038        ret = NULL;
14039        xmlFreeDoc(ctxt->myDoc);
14040        ctxt->myDoc = NULL;
14041     }
14042     if (sax != NULL)
14043         ctxt->sax = oldsax;
14044     xmlFreeParserCtxt(ctxt);
14045     
14046     return(ret);
14047 }
14048
14049 /**
14050  * xmlParseDoc:
14051  * @cur:  a pointer to an array of xmlChar
14052  *
14053  * parse an XML in-memory document and build a tree.
14054  * 
14055  * Returns the resulting document tree
14056  */
14057
14058 xmlDocPtr
14059 xmlParseDoc(const xmlChar *cur) {
14060     return(xmlSAXParseDoc(NULL, cur, 0));
14061 }
14062 #endif /* LIBXML_SAX1_ENABLED */
14063
14064 #ifdef LIBXML_LEGACY_ENABLED
14065 /************************************************************************
14066  *                                                                      *
14067  *      Specific function to keep track of entities references          *
14068  *      and used by the XSLT debugger                                   *
14069  *                                                                      *
14070  ************************************************************************/
14071
14072 static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14073
14074 /**
14075  * xmlAddEntityReference:
14076  * @ent : A valid entity
14077  * @firstNode : A valid first node for children of entity
14078  * @lastNode : A valid last node of children entity 
14079  *
14080  * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14081  */
14082 static void
14083 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14084                       xmlNodePtr lastNode)
14085 {
14086     if (xmlEntityRefFunc != NULL) {
14087         (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14088     }
14089 }
14090
14091
14092 /**
14093  * xmlSetEntityReferenceFunc:
14094  * @func: A valid function
14095  *
14096  * Set the function to call call back when a xml reference has been made
14097  */
14098 void
14099 xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14100 {
14101     xmlEntityRefFunc = func;
14102 }
14103 #endif /* LIBXML_LEGACY_ENABLED */
14104
14105 /************************************************************************
14106  *                                                                      *
14107  *                              Miscellaneous                           *
14108  *                                                                      *
14109  ************************************************************************/
14110
14111 #ifdef LIBXML_XPATH_ENABLED
14112 #include <libxml/xpath.h>
14113 #endif
14114
14115 extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
14116 static int xmlParserInitialized = 0;
14117
14118 /**
14119  * xmlInitParser:
14120  *
14121  * Initialization function for the XML parser.
14122  * This is not reentrant. Call once before processing in case of
14123  * use in multithreaded programs.
14124  */
14125
14126 void
14127 xmlInitParser(void) {
14128     if (xmlParserInitialized != 0)
14129         return;
14130
14131 #ifdef LIBXML_THREAD_ENABLED
14132     __xmlGlobalInitMutexLock();
14133     if (xmlParserInitialized == 0) {
14134 #endif
14135         xmlInitThreads();
14136         xmlInitGlobals();
14137         if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
14138             (xmlGenericError == NULL))
14139             initGenericErrorDefaultFunc(NULL);
14140         xmlInitMemory();
14141         xmlInitCharEncodingHandlers();
14142         xmlDefaultSAXHandlerInit();
14143         xmlRegisterDefaultInputCallbacks();
14144 #ifdef LIBXML_OUTPUT_ENABLED
14145         xmlRegisterDefaultOutputCallbacks();
14146 #endif /* LIBXML_OUTPUT_ENABLED */
14147 #ifdef LIBXML_HTML_ENABLED
14148         htmlInitAutoClose();
14149         htmlDefaultSAXHandlerInit();
14150 #endif
14151 #ifdef LIBXML_XPATH_ENABLED
14152         xmlXPathInit();
14153 #endif
14154         xmlParserInitialized = 1;
14155 #ifdef LIBXML_THREAD_ENABLED
14156     }
14157     __xmlGlobalInitMutexUnlock();
14158 #endif
14159 }
14160
14161 /**
14162  * xmlCleanupParser:
14163  *
14164  * This function name is somewhat misleading. It does not clean up
14165  * parser state, it cleans up memory allocated by the library itself.
14166  * It is a cleanup function for the XML library. It tries to reclaim all
14167  * related global memory allocated for the library processing.
14168  * It doesn't deallocate any document related memory. One should
14169  * call xmlCleanupParser() only when the process has finished using
14170  * the library and all XML/HTML documents built with it.
14171  * See also xmlInitParser() which has the opposite function of preparing
14172  * the library for operations.
14173  *
14174  * WARNING: if your application is multithreaded or has plugin support
14175  *          calling this may crash the application if another thread or
14176  *          a plugin is still using libxml2. It's sometimes very hard to
14177  *          guess if libxml2 is in use in the application, some libraries
14178  *          or plugins may use it without notice. In case of doubt abstain
14179  *          from calling this function or do it just before calling exit()
14180  *          to avoid leak reports from valgrind !
14181  */
14182
14183 void
14184 xmlCleanupParser(void) {
14185     if (!xmlParserInitialized)
14186         return;
14187
14188     xmlCleanupCharEncodingHandlers();
14189 #ifdef LIBXML_CATALOG_ENABLED
14190     xmlCatalogCleanup();
14191 #endif
14192     xmlDictCleanup();
14193     xmlCleanupInputCallbacks();
14194 #ifdef LIBXML_OUTPUT_ENABLED
14195     xmlCleanupOutputCallbacks();
14196 #endif
14197 #ifdef LIBXML_SCHEMAS_ENABLED
14198     xmlSchemaCleanupTypes();
14199     xmlRelaxNGCleanupTypes();
14200 #endif
14201     xmlCleanupGlobals();
14202     xmlResetLastError();
14203     xmlCleanupThreads(); /* must be last if called not from the main thread */
14204     xmlCleanupMemory();
14205     xmlParserInitialized = 0;
14206 }
14207
14208 /************************************************************************
14209  *                                                                      *
14210  *      New set (2.6.0) of simpler and more flexible APIs               *
14211  *                                                                      *
14212  ************************************************************************/
14213
14214 /**
14215  * DICT_FREE:
14216  * @str:  a string
14217  *
14218  * Free a string if it is not owned by the "dict" dictionnary in the
14219  * current scope
14220  */
14221 #define DICT_FREE(str)                                          \
14222         if ((str) && ((!dict) ||                                \
14223             (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14224             xmlFree((char *)(str));
14225
14226 /**
14227  * xmlCtxtReset:
14228  * @ctxt: an XML parser context
14229  *
14230  * Reset a parser context
14231  */
14232 void
14233 xmlCtxtReset(xmlParserCtxtPtr ctxt)
14234 {
14235     xmlParserInputPtr input;
14236     xmlDictPtr dict;
14237     
14238     if (ctxt == NULL)
14239         return;
14240
14241     dict = ctxt->dict;
14242
14243     while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14244         xmlFreeInputStream(input);
14245     }
14246     ctxt->inputNr = 0;
14247     ctxt->input = NULL;
14248
14249     ctxt->spaceNr = 0;
14250     if (ctxt->spaceTab != NULL) {
14251         ctxt->spaceTab[0] = -1;
14252         ctxt->space = &ctxt->spaceTab[0];
14253     } else {
14254         ctxt->space = NULL;
14255     }
14256
14257
14258     ctxt->nodeNr = 0;
14259     ctxt->node = NULL;
14260
14261     ctxt->nameNr = 0;
14262     ctxt->name = NULL;
14263
14264     DICT_FREE(ctxt->version);
14265     ctxt->version = NULL;
14266     DICT_FREE(ctxt->encoding);
14267     ctxt->encoding = NULL;
14268     DICT_FREE(ctxt->directory);
14269     ctxt->directory = NULL;
14270     DICT_FREE(ctxt->extSubURI);
14271     ctxt->extSubURI = NULL;
14272     DICT_FREE(ctxt->extSubSystem);
14273     ctxt->extSubSystem = NULL;
14274     if (ctxt->myDoc != NULL)
14275         xmlFreeDoc(ctxt->myDoc);
14276     ctxt->myDoc = NULL;
14277
14278     ctxt->standalone = -1;
14279     ctxt->hasExternalSubset = 0;
14280     ctxt->hasPErefs = 0;
14281     ctxt->html = 0;
14282     ctxt->external = 0;
14283     ctxt->instate = XML_PARSER_START;
14284     ctxt->token = 0;
14285
14286     ctxt->wellFormed = 1;
14287     ctxt->nsWellFormed = 1;
14288     ctxt->disableSAX = 0;
14289     ctxt->valid = 1;
14290 #if 0
14291     ctxt->vctxt.userData = ctxt;
14292     ctxt->vctxt.error = xmlParserValidityError;
14293     ctxt->vctxt.warning = xmlParserValidityWarning;
14294 #endif
14295     ctxt->record_info = 0;
14296     ctxt->nbChars = 0;
14297     ctxt->checkIndex = 0;
14298     ctxt->inSubset = 0;
14299     ctxt->errNo = XML_ERR_OK;
14300     ctxt->depth = 0;
14301     ctxt->charset = XML_CHAR_ENCODING_UTF8;
14302     ctxt->catalogs = NULL;
14303     ctxt->nbentities = 0;
14304     ctxt->sizeentities = 0;
14305     xmlInitNodeInfoSeq(&ctxt->node_seq);
14306
14307     if (ctxt->attsDefault != NULL) {
14308         xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
14309         ctxt->attsDefault = NULL;
14310     }
14311     if (ctxt->attsSpecial != NULL) {
14312         xmlHashFree(ctxt->attsSpecial, NULL);
14313         ctxt->attsSpecial = NULL;
14314     }
14315
14316 #ifdef LIBXML_CATALOG_ENABLED
14317     if (ctxt->catalogs != NULL)
14318         xmlCatalogFreeLocal(ctxt->catalogs);
14319 #endif
14320     if (ctxt->lastError.code != XML_ERR_OK)
14321         xmlResetError(&ctxt->lastError);
14322 }
14323
14324 /**
14325  * xmlCtxtResetPush:
14326  * @ctxt: an XML parser context
14327  * @chunk:  a pointer to an array of chars
14328  * @size:  number of chars in the array
14329  * @filename:  an optional file name or URI
14330  * @encoding:  the document encoding, or NULL
14331  *
14332  * Reset a push parser context
14333  *
14334  * Returns 0 in case of success and 1 in case of error
14335  */
14336 int
14337 xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14338                  int size, const char *filename, const char *encoding)
14339 {
14340     xmlParserInputPtr inputStream;
14341     xmlParserInputBufferPtr buf;
14342     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14343
14344     if (ctxt == NULL)
14345         return(1);
14346
14347     if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14348         enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14349
14350     buf = xmlAllocParserInputBuffer(enc);
14351     if (buf == NULL)
14352         return(1);
14353
14354     if (ctxt == NULL) {
14355         xmlFreeParserInputBuffer(buf);
14356         return(1);
14357     }
14358
14359     xmlCtxtReset(ctxt);
14360
14361     if (ctxt->pushTab == NULL) {
14362         ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
14363                                             sizeof(xmlChar *));
14364         if (ctxt->pushTab == NULL) {
14365             xmlErrMemory(ctxt, NULL);
14366             xmlFreeParserInputBuffer(buf);
14367             return(1);
14368         }
14369     }
14370
14371     if (filename == NULL) {
14372         ctxt->directory = NULL;
14373     } else {
14374         ctxt->directory = xmlParserGetDirectory(filename);
14375     }
14376
14377     inputStream = xmlNewInputStream(ctxt);
14378     if (inputStream == NULL) {
14379         xmlFreeParserInputBuffer(buf);
14380         return(1);
14381     }
14382
14383     if (filename == NULL)
14384         inputStream->filename = NULL;
14385     else
14386         inputStream->filename = (char *)
14387             xmlCanonicPath((const xmlChar *) filename);
14388     inputStream->buf = buf;
14389     inputStream->base = inputStream->buf->buffer->content;
14390     inputStream->cur = inputStream->buf->buffer->content;
14391     inputStream->end =
14392         &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
14393
14394     inputPush(ctxt, inputStream);
14395
14396     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14397         (ctxt->input->buf != NULL)) {
14398         int base = ctxt->input->base - ctxt->input->buf->buffer->content;
14399         int cur = ctxt->input->cur - ctxt->input->base;
14400
14401         xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14402
14403         ctxt->input->base = ctxt->input->buf->buffer->content + base;
14404         ctxt->input->cur = ctxt->input->base + cur;
14405         ctxt->input->end =
14406             &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->
14407                                                use];
14408 #ifdef DEBUG_PUSH
14409         xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
14410 #endif
14411     }
14412
14413     if (encoding != NULL) {
14414         xmlCharEncodingHandlerPtr hdlr;
14415
14416         if (ctxt->encoding != NULL)
14417             xmlFree((xmlChar *) ctxt->encoding);
14418         ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14419
14420         hdlr = xmlFindCharEncodingHandler(encoding);
14421         if (hdlr != NULL) {
14422             xmlSwitchToEncoding(ctxt, hdlr);
14423         } else {
14424             xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14425                               "Unsupported encoding %s\n", BAD_CAST encoding);
14426         }
14427     } else if (enc != XML_CHAR_ENCODING_NONE) {
14428         xmlSwitchEncoding(ctxt, enc);
14429     }
14430
14431     return(0);
14432 }
14433
14434
14435 /**
14436  * xmlCtxtUseOptionsInternal:
14437  * @ctxt: an XML parser context
14438  * @options:  a combination of xmlParserOption
14439  * @encoding:  the user provided encoding to use
14440  *
14441  * Applies the options to the parser context
14442  *
14443  * Returns 0 in case of success, the set of unknown or unimplemented options
14444  *         in case of error.
14445  */
14446 static int
14447 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
14448 {
14449     if (ctxt == NULL)
14450         return(-1);
14451     if (encoding != NULL) {
14452         if (ctxt->encoding != NULL)
14453             xmlFree((xmlChar *) ctxt->encoding);
14454         ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14455     }
14456     if (options & XML_PARSE_RECOVER) {
14457         ctxt->recovery = 1;
14458         options -= XML_PARSE_RECOVER;
14459         ctxt->options |= XML_PARSE_RECOVER;
14460     } else
14461         ctxt->recovery = 0;
14462     if (options & XML_PARSE_DTDLOAD) {
14463         ctxt->loadsubset = XML_DETECT_IDS;
14464         options -= XML_PARSE_DTDLOAD;
14465         ctxt->options |= XML_PARSE_DTDLOAD;
14466     } else
14467         ctxt->loadsubset = 0;
14468     if (options & XML_PARSE_DTDATTR) {
14469         ctxt->loadsubset |= XML_COMPLETE_ATTRS;
14470         options -= XML_PARSE_DTDATTR;
14471         ctxt->options |= XML_PARSE_DTDATTR;
14472     }
14473     if (options & XML_PARSE_NOENT) {
14474         ctxt->replaceEntities = 1;
14475         /* ctxt->loadsubset |= XML_DETECT_IDS; */
14476         options -= XML_PARSE_NOENT;
14477         ctxt->options |= XML_PARSE_NOENT;
14478     } else
14479         ctxt->replaceEntities = 0;
14480     if (options & XML_PARSE_PEDANTIC) {
14481         ctxt->pedantic = 1;
14482         options -= XML_PARSE_PEDANTIC;
14483         ctxt->options |= XML_PARSE_PEDANTIC;
14484     } else
14485         ctxt->pedantic = 0;
14486     if (options & XML_PARSE_NOBLANKS) {
14487         ctxt->keepBlanks = 0;
14488         ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
14489         options -= XML_PARSE_NOBLANKS;
14490         ctxt->options |= XML_PARSE_NOBLANKS;
14491     } else
14492         ctxt->keepBlanks = 1;
14493     if (options & XML_PARSE_DTDVALID) {
14494         ctxt->validate = 1;
14495         if (options & XML_PARSE_NOWARNING)
14496             ctxt->vctxt.warning = NULL;
14497         if (options & XML_PARSE_NOERROR)
14498             ctxt->vctxt.error = NULL;
14499         options -= XML_PARSE_DTDVALID;
14500         ctxt->options |= XML_PARSE_DTDVALID;
14501     } else
14502         ctxt->validate = 0;
14503     if (options & XML_PARSE_NOWARNING) {
14504         ctxt->sax->warning = NULL;
14505         options -= XML_PARSE_NOWARNING;
14506     }
14507     if (options & XML_PARSE_NOERROR) {
14508         ctxt->sax->error = NULL;
14509         ctxt->sax->fatalError = NULL;
14510         options -= XML_PARSE_NOERROR;
14511     }
14512 #ifdef LIBXML_SAX1_ENABLED
14513     if (options & XML_PARSE_SAX1) {
14514         ctxt->sax->startElement = xmlSAX2StartElement;
14515         ctxt->sax->endElement = xmlSAX2EndElement;
14516         ctxt->sax->startElementNs = NULL;
14517         ctxt->sax->endElementNs = NULL;
14518         ctxt->sax->initialized = 1;
14519         options -= XML_PARSE_SAX1;
14520         ctxt->options |= XML_PARSE_SAX1;
14521     }
14522 #endif /* LIBXML_SAX1_ENABLED */
14523     if (options & XML_PARSE_NODICT) {
14524         ctxt->dictNames = 0;
14525         options -= XML_PARSE_NODICT;
14526         ctxt->options |= XML_PARSE_NODICT;
14527     } else {
14528         ctxt->dictNames = 1;
14529     }
14530     if (options & XML_PARSE_NOCDATA) {
14531         ctxt->sax->cdataBlock = NULL;
14532         options -= XML_PARSE_NOCDATA;
14533         ctxt->options |= XML_PARSE_NOCDATA;
14534     }
14535     if (options & XML_PARSE_NSCLEAN) {
14536         ctxt->options |= XML_PARSE_NSCLEAN;
14537         options -= XML_PARSE_NSCLEAN;
14538     }
14539     if (options & XML_PARSE_NONET) {
14540         ctxt->options |= XML_PARSE_NONET;
14541         options -= XML_PARSE_NONET;
14542     }
14543     if (options & XML_PARSE_COMPACT) {
14544         ctxt->options |= XML_PARSE_COMPACT;
14545         options -= XML_PARSE_COMPACT;
14546     }
14547     if (options & XML_PARSE_OLD10) {
14548         ctxt->options |= XML_PARSE_OLD10;
14549         options -= XML_PARSE_OLD10;
14550     }
14551     if (options & XML_PARSE_NOBASEFIX) {
14552         ctxt->options |= XML_PARSE_NOBASEFIX;
14553         options -= XML_PARSE_NOBASEFIX;
14554     }
14555     if (options & XML_PARSE_HUGE) {
14556         ctxt->options |= XML_PARSE_HUGE;
14557         options -= XML_PARSE_HUGE;
14558     }
14559     if (options & XML_PARSE_OLDSAX) {
14560         ctxt->options |= XML_PARSE_OLDSAX;
14561         options -= XML_PARSE_OLDSAX;
14562     }
14563     ctxt->linenumbers = 1;
14564     return (options);
14565 }
14566
14567 /**
14568  * xmlCtxtUseOptions:
14569  * @ctxt: an XML parser context
14570  * @options:  a combination of xmlParserOption
14571  *
14572  * Applies the options to the parser context
14573  *
14574  * Returns 0 in case of success, the set of unknown or unimplemented options
14575  *         in case of error.
14576  */
14577 int
14578 xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
14579 {
14580    return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
14581 }
14582
14583 /**
14584  * xmlDoRead:
14585  * @ctxt:  an XML parser context
14586  * @URL:  the base URL to use for the document
14587  * @encoding:  the document encoding, or NULL
14588  * @options:  a combination of xmlParserOption
14589  * @reuse:  keep the context for reuse
14590  *
14591  * Common front-end for the xmlRead functions
14592  *
14593  * Returns the resulting document tree or NULL
14594  */
14595 static xmlDocPtr
14596 xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
14597           int options, int reuse)
14598 {
14599     xmlDocPtr ret;
14600
14601     xmlCtxtUseOptionsInternal(ctxt, options, encoding);
14602     if (encoding != NULL) {
14603         xmlCharEncodingHandlerPtr hdlr;
14604
14605         hdlr = xmlFindCharEncodingHandler(encoding);
14606         if (hdlr != NULL)
14607             xmlSwitchToEncoding(ctxt, hdlr);
14608     }
14609     if ((URL != NULL) && (ctxt->input != NULL) &&
14610         (ctxt->input->filename == NULL))
14611         ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
14612     xmlParseDocument(ctxt);
14613     if ((ctxt->wellFormed) || ctxt->recovery)
14614         ret = ctxt->myDoc;
14615     else {
14616         ret = NULL;
14617         if (ctxt->myDoc != NULL) {
14618             xmlFreeDoc(ctxt->myDoc);
14619         }
14620     }
14621     ctxt->myDoc = NULL;
14622     if (!reuse) {
14623         xmlFreeParserCtxt(ctxt);
14624     }
14625
14626     return (ret);
14627 }
14628
14629 /**
14630  * xmlReadDoc:
14631  * @cur:  a pointer to a zero terminated string
14632  * @URL:  the base URL to use for the document
14633  * @encoding:  the document encoding, or NULL
14634  * @options:  a combination of xmlParserOption
14635  *
14636  * parse an XML in-memory document and build a tree.
14637  * 
14638  * Returns the resulting document tree
14639  */
14640 xmlDocPtr
14641 xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
14642 {
14643     xmlParserCtxtPtr ctxt;
14644
14645     if (cur == NULL)
14646         return (NULL);
14647
14648     ctxt = xmlCreateDocParserCtxt(cur);
14649     if (ctxt == NULL)
14650         return (NULL);
14651     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14652 }
14653
14654 /**
14655  * xmlReadFile:
14656  * @filename:  a file or URL
14657  * @encoding:  the document encoding, or NULL
14658  * @options:  a combination of xmlParserOption
14659  *
14660  * parse an XML file from the filesystem or the network.
14661  * 
14662  * Returns the resulting document tree
14663  */
14664 xmlDocPtr
14665 xmlReadFile(const char *filename, const char *encoding, int options)
14666 {
14667     xmlParserCtxtPtr ctxt;
14668
14669     ctxt = xmlCreateURLParserCtxt(filename, options);
14670     if (ctxt == NULL)
14671         return (NULL);
14672     return (xmlDoRead(ctxt, NULL, encoding, options, 0));
14673 }
14674
14675 /**
14676  * xmlReadMemory:
14677  * @buffer:  a pointer to a char array
14678  * @size:  the size of the array
14679  * @URL:  the base URL to use for the document
14680  * @encoding:  the document encoding, or NULL
14681  * @options:  a combination of xmlParserOption
14682  *
14683  * parse an XML in-memory document and build a tree.
14684  * 
14685  * Returns the resulting document tree
14686  */
14687 xmlDocPtr
14688 xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
14689 {
14690     xmlParserCtxtPtr ctxt;
14691
14692     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14693     if (ctxt == NULL)
14694         return (NULL);
14695     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14696 }
14697
14698 /**
14699  * xmlReadFd:
14700  * @fd:  an open file descriptor
14701  * @URL:  the base URL to use for the document
14702  * @encoding:  the document encoding, or NULL
14703  * @options:  a combination of xmlParserOption
14704  *
14705  * parse an XML from a file descriptor and build a tree.
14706  * NOTE that the file descriptor will not be closed when the
14707  *      reader is closed or reset.
14708  * 
14709  * Returns the resulting document tree
14710  */
14711 xmlDocPtr
14712 xmlReadFd(int fd, const char *URL, const char *encoding, int options)
14713 {
14714     xmlParserCtxtPtr ctxt;
14715     xmlParserInputBufferPtr input;
14716     xmlParserInputPtr stream;
14717
14718     if (fd < 0)
14719         return (NULL);
14720
14721     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14722     if (input == NULL)
14723         return (NULL);
14724     input->closecallback = NULL;
14725     ctxt = xmlNewParserCtxt();
14726     if (ctxt == NULL) {
14727         xmlFreeParserInputBuffer(input);
14728         return (NULL);
14729     }
14730     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14731     if (stream == NULL) {
14732         xmlFreeParserInputBuffer(input);
14733         xmlFreeParserCtxt(ctxt);
14734         return (NULL);
14735     }
14736     inputPush(ctxt, stream);
14737     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14738 }
14739
14740 /**
14741  * xmlReadIO:
14742  * @ioread:  an I/O read function
14743  * @ioclose:  an I/O close function
14744  * @ioctx:  an I/O handler
14745  * @URL:  the base URL to use for the document
14746  * @encoding:  the document encoding, or NULL
14747  * @options:  a combination of xmlParserOption
14748  *
14749  * parse an XML document from I/O functions and source and build a tree.
14750  * 
14751  * Returns the resulting document tree
14752  */
14753 xmlDocPtr
14754 xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
14755           void *ioctx, const char *URL, const char *encoding, int options)
14756 {
14757     xmlParserCtxtPtr ctxt;
14758     xmlParserInputBufferPtr input;
14759     xmlParserInputPtr stream;
14760
14761     if (ioread == NULL)
14762         return (NULL);
14763
14764     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14765                                          XML_CHAR_ENCODING_NONE);
14766     if (input == NULL)
14767         return (NULL);
14768     ctxt = xmlNewParserCtxt();
14769     if (ctxt == NULL) {
14770         xmlFreeParserInputBuffer(input);
14771         return (NULL);
14772     }
14773     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14774     if (stream == NULL) {
14775         xmlFreeParserInputBuffer(input);
14776         xmlFreeParserCtxt(ctxt);
14777         return (NULL);
14778     }
14779     inputPush(ctxt, stream);
14780     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14781 }
14782
14783 /**
14784  * xmlCtxtReadDoc:
14785  * @ctxt:  an XML parser context
14786  * @cur:  a pointer to a zero terminated string
14787  * @URL:  the base URL to use for the document
14788  * @encoding:  the document encoding, or NULL
14789  * @options:  a combination of xmlParserOption
14790  *
14791  * parse an XML in-memory document and build a tree.
14792  * This reuses the existing @ctxt parser context
14793  * 
14794  * Returns the resulting document tree
14795  */
14796 xmlDocPtr
14797 xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
14798                const char *URL, const char *encoding, int options)
14799 {
14800     xmlParserInputPtr stream;
14801
14802     if (cur == NULL)
14803         return (NULL);
14804     if (ctxt == NULL)
14805         return (NULL);
14806
14807     xmlCtxtReset(ctxt);
14808
14809     stream = xmlNewStringInputStream(ctxt, cur);
14810     if (stream == NULL) {
14811         return (NULL);
14812     }
14813     inputPush(ctxt, stream);
14814     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14815 }
14816
14817 /**
14818  * xmlCtxtReadFile:
14819  * @ctxt:  an XML parser context
14820  * @filename:  a file or URL
14821  * @encoding:  the document encoding, or NULL
14822  * @options:  a combination of xmlParserOption
14823  *
14824  * parse an XML file from the filesystem or the network.
14825  * This reuses the existing @ctxt parser context
14826  * 
14827  * Returns the resulting document tree
14828  */
14829 xmlDocPtr
14830 xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
14831                 const char *encoding, int options)
14832 {
14833     xmlParserInputPtr stream;
14834
14835     if (filename == NULL)
14836         return (NULL);
14837     if (ctxt == NULL)
14838         return (NULL);
14839
14840     xmlCtxtReset(ctxt);
14841
14842     stream = xmlLoadExternalEntity(filename, NULL, ctxt);
14843     if (stream == NULL) {
14844         return (NULL);
14845     }
14846     inputPush(ctxt, stream);
14847     return (xmlDoRead(ctxt, NULL, encoding, options, 1));
14848 }
14849
14850 /**
14851  * xmlCtxtReadMemory:
14852  * @ctxt:  an XML parser context
14853  * @buffer:  a pointer to a char array
14854  * @size:  the size of the array
14855  * @URL:  the base URL to use for the document
14856  * @encoding:  the document encoding, or NULL
14857  * @options:  a combination of xmlParserOption
14858  *
14859  * parse an XML in-memory document and build a tree.
14860  * This reuses the existing @ctxt parser context
14861  * 
14862  * Returns the resulting document tree
14863  */
14864 xmlDocPtr
14865 xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
14866                   const char *URL, const char *encoding, int options)
14867 {
14868     xmlParserInputBufferPtr input;
14869     xmlParserInputPtr stream;
14870
14871     if (ctxt == NULL)
14872         return (NULL);
14873     if (buffer == NULL)
14874         return (NULL);
14875
14876     xmlCtxtReset(ctxt);
14877
14878     input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14879     if (input == NULL) {
14880         return(NULL);
14881     }
14882
14883     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14884     if (stream == NULL) {
14885         xmlFreeParserInputBuffer(input);
14886         return(NULL);
14887     }
14888
14889     inputPush(ctxt, stream);
14890     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14891 }
14892
14893 /**
14894  * xmlCtxtReadFd:
14895  * @ctxt:  an XML parser context
14896  * @fd:  an open file descriptor
14897  * @URL:  the base URL to use for the document
14898  * @encoding:  the document encoding, or NULL
14899  * @options:  a combination of xmlParserOption
14900  *
14901  * parse an XML from a file descriptor and build a tree.
14902  * This reuses the existing @ctxt parser context
14903  * NOTE that the file descriptor will not be closed when the
14904  *      reader is closed or reset.
14905  * 
14906  * Returns the resulting document tree
14907  */
14908 xmlDocPtr
14909 xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
14910               const char *URL, const char *encoding, int options)
14911 {
14912     xmlParserInputBufferPtr input;
14913     xmlParserInputPtr stream;
14914
14915     if (fd < 0)
14916         return (NULL);
14917     if (ctxt == NULL)
14918         return (NULL);
14919
14920     xmlCtxtReset(ctxt);
14921
14922
14923     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14924     if (input == NULL)
14925         return (NULL);
14926     input->closecallback = NULL;
14927     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14928     if (stream == NULL) {
14929         xmlFreeParserInputBuffer(input);
14930         return (NULL);
14931     }
14932     inputPush(ctxt, stream);
14933     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14934 }
14935
14936 /**
14937  * xmlCtxtReadIO:
14938  * @ctxt:  an XML parser context
14939  * @ioread:  an I/O read function
14940  * @ioclose:  an I/O close function
14941  * @ioctx:  an I/O handler
14942  * @URL:  the base URL to use for the document
14943  * @encoding:  the document encoding, or NULL
14944  * @options:  a combination of xmlParserOption
14945  *
14946  * parse an XML document from I/O functions and source and build a tree.
14947  * This reuses the existing @ctxt parser context
14948  * 
14949  * Returns the resulting document tree
14950  */
14951 xmlDocPtr
14952 xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
14953               xmlInputCloseCallback ioclose, void *ioctx,
14954               const char *URL,
14955               const char *encoding, int options)
14956 {
14957     xmlParserInputBufferPtr input;
14958     xmlParserInputPtr stream;
14959
14960     if (ioread == NULL)
14961         return (NULL);
14962     if (ctxt == NULL)
14963         return (NULL);
14964
14965     xmlCtxtReset(ctxt);
14966
14967     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14968                                          XML_CHAR_ENCODING_NONE);
14969     if (input == NULL)
14970         return (NULL);
14971     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14972     if (stream == NULL) {
14973         xmlFreeParserInputBuffer(input);
14974         return (NULL);
14975     }
14976     inputPush(ctxt, stream);
14977     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14978 }
14979
14980 #define bottom_parser
14981 #include "elfgcchack.h"