BRANCH release for 2.5.x critical patches
[baserock-morphs: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 <libxml/xmlmemory.h>
45 #include <libxml/threads.h>
46 #include <libxml/globals.h>
47 #include <libxml/tree.h>
48 #include <libxml/parser.h>
49 #include <libxml/parserInternals.h>
50 #include <libxml/valid.h>
51 #include <libxml/entities.h>
52 #include <libxml/xmlerror.h>
53 #include <libxml/encoding.h>
54 #include <libxml/xmlIO.h>
55 #include <libxml/uri.h>
56 #ifdef LIBXML_CATALOG_ENABLED
57 #include <libxml/catalog.h>
58 #endif
59
60 #ifdef HAVE_CTYPE_H
61 #include <ctype.h>
62 #endif
63 #ifdef HAVE_STDLIB_H
64 #include <stdlib.h>
65 #endif
66 #ifdef HAVE_SYS_STAT_H
67 #include <sys/stat.h>
68 #endif
69 #ifdef HAVE_FCNTL_H
70 #include <fcntl.h>
71 #endif
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75 #ifdef HAVE_ZLIB_H
76 #include <zlib.h>
77 #endif
78
79 /**
80  * MAX_DEPTH:
81  *
82  * arbitrary depth limit for the XML documents that we allow to 
83  * process. This is not a limitation of the parser but a safety 
84  * boundary feature.
85  */
86 #define MAX_DEPTH 1024
87
88 #define XML_PARSER_BIG_BUFFER_SIZE 300
89 #define XML_PARSER_BUFFER_SIZE 100
90
91 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
92
93 /*
94  * List of XML prefixed PI allowed by W3C specs
95  */
96
97 static const char *xmlW3CPIs[] = {
98     "xml-stylesheet",
99     NULL
100 };
101
102 /* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
103 xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
104                                        const xmlChar **str);
105
106 static int
107 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
108                       xmlSAXHandlerPtr sax,
109                       void *user_data, int depth, const xmlChar *URL,
110                       const xmlChar *ID, xmlNodePtr *list);
111
112 static void
113 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
114                       xmlNodePtr lastNode);
115
116 static int
117 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
118                       const xmlChar *string, void *user_data, xmlNodePtr *lst);
119 /************************************************************************
120  *                                                                      *
121  *              Parser stacks related functions and macros              *
122  *                                                                      *
123  ************************************************************************/
124
125 xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
126                                      const xmlChar ** str);
127
128 /**
129  * inputPush:
130  * @ctxt:  an XML parser context
131  * @value:  the parser input
132  *
133  * Pushes a new parser input on top of the input stack
134  *
135  * Returns 0 in case of error, the index in the stack otherwise
136  */
137 extern int
138 inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
139 {
140     if (ctxt->inputNr >= ctxt->inputMax) {
141         ctxt->inputMax *= 2;
142         ctxt->inputTab =
143             (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
144                                              ctxt->inputMax *
145                                              sizeof(ctxt->inputTab[0]));
146         if (ctxt->inputTab == NULL) {
147             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
148             return (0);
149         }
150     }
151     ctxt->inputTab[ctxt->inputNr] = value;
152     ctxt->input = value;
153     return (ctxt->inputNr++);
154 }
155 /**
156  * inputPop:
157  * @ctxt: an XML parser context
158  *
159  * Pops the top parser input from the input stack
160  *
161  * Returns the input just removed
162  */
163 extern xmlParserInputPtr
164 inputPop(xmlParserCtxtPtr ctxt)
165 {
166     xmlParserInputPtr ret;
167
168     if (ctxt->inputNr <= 0)
169         return (0);
170     ctxt->inputNr--;
171     if (ctxt->inputNr > 0)
172         ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
173     else
174         ctxt->input = NULL;
175     ret = ctxt->inputTab[ctxt->inputNr];
176     ctxt->inputTab[ctxt->inputNr] = 0;
177     return (ret);
178 }
179 /**
180  * nodePush:
181  * @ctxt:  an XML parser context
182  * @value:  the element node
183  *
184  * Pushes a new element node on top of the node stack
185  *
186  * Returns 0 in case of error, the index in the stack otherwise
187  */
188 extern int
189 nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
190 {
191     if (ctxt->nodeNr >= ctxt->nodeMax) {
192         ctxt->nodeMax *= 2;
193         ctxt->nodeTab =
194             (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
195                                       ctxt->nodeMax *
196                                       sizeof(ctxt->nodeTab[0]));
197         if (ctxt->nodeTab == NULL) {
198             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
199             return (0);
200         }
201     }
202 #ifdef MAX_DEPTH
203     if (ctxt->nodeNr > MAX_DEPTH) {
204         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
205             ctxt->sax->error(ctxt->userData, 
206                  "Excessive depth in document: change MAX_DEPTH = %d\n",
207                              MAX_DEPTH);
208         ctxt->wellFormed = 0;
209         ctxt->instate = XML_PARSER_EOF;
210         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
211         return(0);
212     }
213 #endif
214     ctxt->nodeTab[ctxt->nodeNr] = value;
215     ctxt->node = value;
216     return (ctxt->nodeNr++);
217 }
218 /**
219  * nodePop:
220  * @ctxt: an XML parser context
221  *
222  * Pops the top element node from the node stack
223  *
224  * Returns the node just removed
225  */
226 extern xmlNodePtr
227 nodePop(xmlParserCtxtPtr ctxt)
228 {
229     xmlNodePtr ret;
230
231     if (ctxt->nodeNr <= 0)
232         return (0);
233     ctxt->nodeNr--;
234     if (ctxt->nodeNr > 0)
235         ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
236     else
237         ctxt->node = NULL;
238     ret = ctxt->nodeTab[ctxt->nodeNr];
239     ctxt->nodeTab[ctxt->nodeNr] = 0;
240     return (ret);
241 }
242 /**
243  * namePush:
244  * @ctxt:  an XML parser context
245  * @value:  the element name
246  *
247  * Pushes a new element name on top of the name stack
248  *
249  * Returns 0 in case of error, the index in the stack otherwise
250  */
251 extern int
252 namePush(xmlParserCtxtPtr ctxt, xmlChar * value)
253 {
254     if (ctxt->nameNr >= ctxt->nameMax) {
255         ctxt->nameMax *= 2;
256         ctxt->nameTab =
257             (xmlChar * *)xmlRealloc(ctxt->nameTab,
258                                     ctxt->nameMax *
259                                     sizeof(ctxt->nameTab[0]));
260         if (ctxt->nameTab == NULL) {
261             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
262             return (0);
263         }
264     }
265     ctxt->nameTab[ctxt->nameNr] = value;
266     ctxt->name = value;
267     return (ctxt->nameNr++);
268 }
269 /**
270  * namePop:
271  * @ctxt: an XML parser context
272  *
273  * Pops the top element name from the name stack
274  *
275  * Returns the name just removed
276  */
277 extern xmlChar *
278 namePop(xmlParserCtxtPtr ctxt)
279 {
280     xmlChar *ret;
281
282     if (ctxt->nameNr <= 0)
283         return (0);
284     ctxt->nameNr--;
285     if (ctxt->nameNr > 0)
286         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
287     else
288         ctxt->name = NULL;
289     ret = ctxt->nameTab[ctxt->nameNr];
290     ctxt->nameTab[ctxt->nameNr] = 0;
291     return (ret);
292 }
293
294 static int spacePush(xmlParserCtxtPtr ctxt, int val) {
295     if (ctxt->spaceNr >= ctxt->spaceMax) {
296         ctxt->spaceMax *= 2;
297         ctxt->spaceTab = (int *) xmlRealloc(ctxt->spaceTab,
298                      ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
299         if (ctxt->spaceTab == NULL) {
300             xmlGenericError(xmlGenericErrorContext,
301                     "realloc failed !\n");
302             return(0);
303         }
304     }
305     ctxt->spaceTab[ctxt->spaceNr] = val;
306     ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
307     return(ctxt->spaceNr++);
308 }
309
310 static int spacePop(xmlParserCtxtPtr ctxt) {
311     int ret;
312     if (ctxt->spaceNr <= 0) return(0);
313     ctxt->spaceNr--;
314     if (ctxt->spaceNr > 0)
315         ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
316     else
317         ctxt->space = NULL;
318     ret = ctxt->spaceTab[ctxt->spaceNr];
319     ctxt->spaceTab[ctxt->spaceNr] = -1;
320     return(ret);
321 }
322
323 /*
324  * Macros for accessing the content. Those should be used only by the parser,
325  * and not exported.
326  *
327  * Dirty macros, i.e. one often need to make assumption on the context to
328  * use them
329  *
330  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
331  *           To be used with extreme caution since operations consuming
332  *           characters may move the input buffer to a different location !
333  *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
334  *           This should be used internally by the parser
335  *           only to compare to ASCII values otherwise it would break when
336  *           running with UTF-8 encoding.
337  *   RAW     same as CUR but in the input buffer, bypass any token
338  *           extraction that may have been done
339  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
340  *           to compare on ASCII based substring.
341  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
342  *           strings without newlines within the parser.
343  *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII 
344  *           defined char within the parser.
345  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
346  *
347  *   NEXT    Skip to the next character, this does the proper decoding
348  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
349  *   NEXTL(l) Skip the current unicode character of l xmlChars long.
350  *   CUR_CHAR(l) returns the current unicode character (int), set l
351  *           to the number of xmlChars used for the encoding [0-5].
352  *   CUR_SCHAR  same but operate on a string instead of the context
353  *   COPY_BUF  copy the current unicode char to the target buffer, increment
354  *            the index
355  *   GROW, SHRINK  handling of input buffers
356  */
357
358 #define RAW (*ctxt->input->cur)
359 #define CUR (*ctxt->input->cur)
360 #define NXT(val) ctxt->input->cur[(val)]
361 #define CUR_PTR ctxt->input->cur
362
363 #define SKIP(val) do {                                                  \
364     ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);                   \
365     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
366     if ((*ctxt->input->cur == 0) &&                                     \
367         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
368             xmlPopInput(ctxt);                                          \
369   } while (0)
370
371 #define SHRINK if ((ctxt->progressive == 0) &&                          \
372                    (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) && \
373                    (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
374         xmlSHRINK (ctxt);
375
376 static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
377     xmlParserInputShrink(ctxt->input);
378     if ((*ctxt->input->cur == 0) &&
379         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
380             xmlPopInput(ctxt);
381   }
382
383 #define GROW if ((ctxt->progressive == 0) &&                            \
384                  (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
385         xmlGROW (ctxt);
386
387 static void xmlGROW (xmlParserCtxtPtr ctxt) {
388     xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
389     if ((*ctxt->input->cur == 0) &&
390         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
391             xmlPopInput(ctxt);
392 }
393
394 #define SKIP_BLANKS xmlSkipBlankChars(ctxt)
395
396 #define NEXT xmlNextChar(ctxt)
397
398 #define NEXT1 {                                                         \
399         ctxt->input->col++;                                             \
400         ctxt->input->cur++;                                             \
401         ctxt->nbChars++;                                                \
402         if (*ctxt->input->cur == 0)                                     \
403             xmlParserInputGrow(ctxt->input, INPUT_CHUNK);               \
404     }
405
406 #define NEXTL(l) do {                                                   \
407     if (*(ctxt->input->cur) == '\n') {                                  \
408         ctxt->input->line++; ctxt->input->col = 1;                      \
409     } else ctxt->input->col++;                                          \
410     ctxt->input->cur += l;                              \
411     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
412   } while (0)
413
414 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
415 #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
416
417 #define COPY_BUF(l,b,i,v)                                               \
418     if (l == 1) b[i++] = (xmlChar) v;                                   \
419     else i += xmlCopyCharMultiByte(&b[i],v)
420
421 /**
422  * xmlSkipBlankChars:
423  * @ctxt:  the XML parser context
424  *
425  * skip all blanks character found at that point in the input streams.
426  * It pops up finished entities in the process if allowable at that point.
427  *
428  * Returns the number of space chars skipped
429  */
430
431 int
432 xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
433     int res = 0;
434
435     /*
436      * It's Okay to use CUR/NEXT here since all the blanks are on
437      * the ASCII range.
438      */
439     if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
440         const xmlChar *cur;
441         /*
442          * if we are in the document content, go really fast
443          */
444         cur = ctxt->input->cur;
445         while (IS_BLANK(*cur)) {
446             if (*cur == '\n') {
447                 ctxt->input->line++; ctxt->input->col = 1;
448             }
449             cur++;
450             res++;
451             if (*cur == 0) {
452                 ctxt->input->cur = cur;
453                 xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
454                 cur = ctxt->input->cur;
455             }
456         }
457         ctxt->input->cur = cur;
458     } else {
459         int cur;
460         do {
461             cur = CUR;
462             while (IS_BLANK(cur)) { /* CHECKED tstblanks.xml */
463                 NEXT;
464                 cur = CUR;
465                 res++;
466             }
467             while ((cur == 0) && (ctxt->inputNr > 1) &&
468                    (ctxt->instate != XML_PARSER_COMMENT)) {
469                 xmlPopInput(ctxt);
470                 cur = CUR;
471             }
472             /*
473              * Need to handle support of entities branching here
474              */
475             if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
476         } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
477     }
478     return(res);
479 }
480
481 /************************************************************************
482  *                                                                      *
483  *              Commodity functions to handle entities                  *
484  *                                                                      *
485  ************************************************************************/
486
487 /**
488  * xmlPopInput:
489  * @ctxt:  an XML parser context
490  *
491  * xmlPopInput: the current input pointed by ctxt->input came to an end
492  *          pop it and return the next char.
493  *
494  * Returns the current xmlChar in the parser context
495  */
496 xmlChar
497 xmlPopInput(xmlParserCtxtPtr ctxt) {
498     if (ctxt->inputNr == 1) return(0); /* End of main Input */
499     if (xmlParserDebugEntities)
500         xmlGenericError(xmlGenericErrorContext,
501                 "Popping input %d\n", ctxt->inputNr);
502     xmlFreeInputStream(inputPop(ctxt));
503     if ((*ctxt->input->cur == 0) &&
504         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
505             return(xmlPopInput(ctxt));
506     return(CUR);
507 }
508
509 /**
510  * xmlPushInput:
511  * @ctxt:  an XML parser context
512  * @input:  an XML parser input fragment (entity, XML fragment ...).
513  *
514  * xmlPushInput: switch to a new input stream which is stacked on top
515  *               of the previous one(s).
516  */
517 void
518 xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
519     if (input == NULL) return;
520
521     if (xmlParserDebugEntities) {
522         if ((ctxt->input != NULL) && (ctxt->input->filename))
523             xmlGenericError(xmlGenericErrorContext,
524                     "%s(%d): ", ctxt->input->filename,
525                     ctxt->input->line);
526         xmlGenericError(xmlGenericErrorContext,
527                 "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
528     }
529     inputPush(ctxt, input);
530     GROW;
531 }
532
533 /**
534  * xmlParseCharRef:
535  * @ctxt:  an XML parser context
536  *
537  * parse Reference declarations
538  *
539  * [66] CharRef ::= '&#' [0-9]+ ';' |
540  *                  '&#x' [0-9a-fA-F]+ ';'
541  *
542  * [ WFC: Legal Character ]
543  * Characters referred to using character references must match the
544  * production for Char. 
545  *
546  * Returns the value parsed (as an int), 0 in case of error
547  */
548 int
549 xmlParseCharRef(xmlParserCtxtPtr ctxt) {
550     unsigned int val = 0;
551     int count = 0;
552
553     /*
554      * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
555      */
556     if ((RAW == '&') && (NXT(1) == '#') &&
557         (NXT(2) == 'x')) {
558         SKIP(3);
559         GROW;
560         while (RAW != ';') { /* loop blocked by count */
561             if (count++ > 20) {
562                 count = 0;
563                 GROW;
564             }
565             if ((RAW >= '0') && (RAW <= '9')) 
566                 val = val * 16 + (CUR - '0');
567             else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
568                 val = val * 16 + (CUR - 'a') + 10;
569             else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
570                 val = val * 16 + (CUR - 'A') + 10;
571             else {
572                 ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
573                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
574                     ctxt->sax->error(ctxt->userData, 
575                          "xmlParseCharRef: invalid hexadecimal value\n");
576                 ctxt->wellFormed = 0;
577                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
578                 val = 0;
579                 break;
580             }
581             NEXT;
582             count++;
583         }
584         if (RAW == ';') {
585             /* on purpose to avoid reentrancy problems with NEXT and SKIP */
586             ctxt->input->col++;
587             ctxt->nbChars ++;
588             ctxt->input->cur++;
589         }
590     } else if  ((RAW == '&') && (NXT(1) == '#')) {
591         SKIP(2);
592         GROW;
593         while (RAW != ';') { /* loop blocked by count */
594             if (count++ > 20) {
595                 count = 0;
596                 GROW;
597             }
598             if ((RAW >= '0') && (RAW <= '9')) 
599                 val = val * 10 + (CUR - '0');
600             else {
601                 ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
602                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
603                     ctxt->sax->error(ctxt->userData, 
604                          "xmlParseCharRef: invalid decimal value\n");
605                 ctxt->wellFormed = 0;
606                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
607                 val = 0;
608                 break;
609             }
610             NEXT;
611             count++;
612         }
613         if (RAW == ';') {
614             /* on purpose to avoid reentrancy problems with NEXT and SKIP */
615             ctxt->input->col++;
616             ctxt->nbChars ++;
617             ctxt->input->cur++;
618         }
619     } else {
620         ctxt->errNo = XML_ERR_INVALID_CHARREF;
621         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
622             ctxt->sax->error(ctxt->userData,
623                "xmlParseCharRef: invalid value\n");
624         ctxt->wellFormed = 0;
625         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
626     }
627
628     /*
629      * [ WFC: Legal Character ]
630      * Characters referred to using character references must match the
631      * production for Char. 
632      */
633     if (IS_CHAR(val)) {
634         return(val);
635     } else {
636         ctxt->errNo = XML_ERR_INVALID_CHAR;
637         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
638             ctxt->sax->error(ctxt->userData,
639                              "xmlParseCharRef: invalid xmlChar value %d\n",
640                              val);
641         ctxt->wellFormed = 0;
642         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
643     }
644     return(0);
645 }
646
647 /**
648  * xmlParseStringCharRef:
649  * @ctxt:  an XML parser context
650  * @str:  a pointer to an index in the string
651  *
652  * parse Reference declarations, variant parsing from a string rather
653  * than an an input flow.
654  *
655  * [66] CharRef ::= '&#' [0-9]+ ';' |
656  *                  '&#x' [0-9a-fA-F]+ ';'
657  *
658  * [ WFC: Legal Character ]
659  * Characters referred to using character references must match the
660  * production for Char. 
661  *
662  * Returns the value parsed (as an int), 0 in case of error, str will be
663  *         updated to the current value of the index
664  */
665 static int
666 xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
667     const xmlChar *ptr;
668     xmlChar cur;
669     int val = 0;
670
671     if ((str == NULL) || (*str == NULL)) return(0);
672     ptr = *str;
673     cur = *ptr;
674     if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
675         ptr += 3;
676         cur = *ptr;
677         while (cur != ';') { /* Non input consuming loop */
678             if ((cur >= '0') && (cur <= '9')) 
679                 val = val * 16 + (cur - '0');
680             else if ((cur >= 'a') && (cur <= 'f'))
681                 val = val * 16 + (cur - 'a') + 10;
682             else if ((cur >= 'A') && (cur <= 'F'))
683                 val = val * 16 + (cur - 'A') + 10;
684             else {
685                 ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
686                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
687                     ctxt->sax->error(ctxt->userData, 
688                          "xmlParseStringCharRef: invalid hexadecimal value\n");
689                 ctxt->wellFormed = 0;
690                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
691                 val = 0;
692                 break;
693             }
694             ptr++;
695             cur = *ptr;
696         }
697         if (cur == ';')
698             ptr++;
699     } else if  ((cur == '&') && (ptr[1] == '#')){
700         ptr += 2;
701         cur = *ptr;
702         while (cur != ';') { /* Non input consuming loops */
703             if ((cur >= '0') && (cur <= '9')) 
704                 val = val * 10 + (cur - '0');
705             else {
706                 ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
707                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
708                     ctxt->sax->error(ctxt->userData, 
709                          "xmlParseStringCharRef: invalid decimal value\n");
710                 ctxt->wellFormed = 0;
711                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
712                 val = 0;
713                 break;
714             }
715             ptr++;
716             cur = *ptr;
717         }
718         if (cur == ';')
719             ptr++;
720     } else {
721         ctxt->errNo = XML_ERR_INVALID_CHARREF;
722         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
723             ctxt->sax->error(ctxt->userData,
724                "xmlParseStringCharRef: invalid value\n");
725         ctxt->wellFormed = 0;
726         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
727         return(0);
728     }
729     *str = ptr;
730
731     /*
732      * [ WFC: Legal Character ]
733      * Characters referred to using character references must match the
734      * production for Char. 
735      */
736     if (IS_CHAR(val)) {
737         return(val);
738     } else {
739         ctxt->errNo = XML_ERR_INVALID_CHAR;
740         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
741             ctxt->sax->error(ctxt->userData,
742                              "xmlParseStringCharRef: invalid xmlChar value %d\n", val);
743         ctxt->wellFormed = 0;
744         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
745     }
746     return(0);
747 }
748
749 /**
750  * xmlNewBlanksWrapperInputStream:
751  * @ctxt:  an XML parser context
752  * @entity:  an Entity pointer
753  *
754  * Create a new input stream for wrapping
755  * blanks around a PEReference
756  *
757  * Returns the new input stream or NULL
758  */
759  
760 static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
761  
762 static xmlParserInputPtr
763 xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
764     xmlParserInputPtr input;
765     xmlChar *buffer;
766     size_t length;
767     if (entity == NULL) {
768         ctxt->errNo = XML_ERR_INTERNAL_ERROR;
769         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
770             ctxt->sax->error(ctxt->userData,
771               "internal: xmlNewBlanksWrapperInputStream entity = NULL\n");
772         ctxt->errNo = XML_ERR_INTERNAL_ERROR;
773         return(NULL);
774     }
775     if (xmlParserDebugEntities)
776         xmlGenericError(xmlGenericErrorContext,
777                 "new blanks wrapper for entity: %s\n", entity->name);
778     input = xmlNewInputStream(ctxt);
779     if (input == NULL) {
780         return(NULL);
781     }
782     length = xmlStrlen(entity->name) + 5;
783     buffer = xmlMallocAtomic(length);
784     if (buffer == NULL) {
785         return(NULL);
786     }
787     buffer [0] = ' ';
788     buffer [1] = '%';
789     buffer [length-3] = ';';
790     buffer [length-2] = ' ';
791     buffer [length-1] = 0;
792     memcpy(buffer + 2, entity->name, length - 5);
793     input->free = deallocblankswrapper;
794     input->base = buffer;
795     input->cur = buffer;
796     input->length = length;
797     input->end = &buffer[length];
798     return(input);
799 }
800
801 /**
802  * xmlParserHandlePEReference:
803  * @ctxt:  the parser context
804  * 
805  * [69] PEReference ::= '%' Name ';'
806  *
807  * [ WFC: No Recursion ]
808  * A parsed entity must not contain a recursive
809  * reference to itself, either directly or indirectly. 
810  *
811  * [ WFC: Entity Declared ]
812  * In a document without any DTD, a document with only an internal DTD
813  * subset which contains no parameter entity references, or a document
814  * with "standalone='yes'", ...  ... The declaration of a parameter
815  * entity must precede any reference to it...
816  *
817  * [ VC: Entity Declared ]
818  * In a document with an external subset or external parameter entities
819  * with "standalone='no'", ...  ... The declaration of a parameter entity
820  * must precede any reference to it...
821  *
822  * [ WFC: In DTD ]
823  * Parameter-entity references may only appear in the DTD.
824  * NOTE: misleading but this is handled.
825  *
826  * A PEReference may have been detected in the current input stream
827  * the handling is done accordingly to 
828  *      http://www.w3.org/TR/REC-xml#entproc
829  * i.e. 
830  *   - Included in literal in entity values
831  *   - Included as Parameter Entity reference within DTDs
832  */
833 void
834 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
835     xmlChar *name;
836     xmlEntityPtr entity = NULL;
837     xmlParserInputPtr input;
838
839     if (RAW != '%') return;
840     switch(ctxt->instate) {
841         case XML_PARSER_CDATA_SECTION:
842             return;
843         case XML_PARSER_COMMENT:
844             return;
845         case XML_PARSER_START_TAG:
846             return;
847         case XML_PARSER_END_TAG:
848             return;
849         case XML_PARSER_EOF:
850             ctxt->errNo = XML_ERR_PEREF_AT_EOF;
851             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
852                 ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
853             ctxt->wellFormed = 0;
854             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
855             return;
856         case XML_PARSER_PROLOG:
857         case XML_PARSER_START:
858         case XML_PARSER_MISC:
859             ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
860             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
861                 ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
862             ctxt->wellFormed = 0;
863             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
864             return;
865         case XML_PARSER_ENTITY_DECL:
866         case XML_PARSER_CONTENT:
867         case XML_PARSER_ATTRIBUTE_VALUE:
868         case XML_PARSER_PI:
869         case XML_PARSER_SYSTEM_LITERAL:
870         case XML_PARSER_PUBLIC_LITERAL:
871             /* we just ignore it there */
872             return;
873         case XML_PARSER_EPILOG:
874             ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
875             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
876                 ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
877             ctxt->wellFormed = 0;
878             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
879             return;
880         case XML_PARSER_ENTITY_VALUE:
881             /*
882              * NOTE: in the case of entity values, we don't do the
883              *       substitution here since we need the literal
884              *       entity value to be able to save the internal
885              *       subset of the document.
886              *       This will be handled by xmlStringDecodeEntities
887              */
888             return;
889         case XML_PARSER_DTD:
890             /*
891              * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
892              * In the internal DTD subset, parameter-entity references
893              * can occur only where markup declarations can occur, not
894              * within markup declarations.
895              * In that case this is handled in xmlParseMarkupDecl
896              */
897             if ((ctxt->external == 0) && (ctxt->inputNr == 1))
898                 return;
899             if (IS_BLANK(NXT(1)) || NXT(1) == 0)
900                 return;
901             break;
902         case XML_PARSER_IGNORE:
903             return;
904     }
905
906     NEXT;
907     name = xmlParseName(ctxt);
908     if (xmlParserDebugEntities)
909         xmlGenericError(xmlGenericErrorContext,
910                 "PEReference: %s\n", name);
911     if (name == NULL) {
912         ctxt->errNo = XML_ERR_PEREF_NO_NAME;
913         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
914             ctxt->sax->error(ctxt->userData, "xmlParserHandlePEReference: no name\n");
915         ctxt->wellFormed = 0;
916         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
917     } else {
918         if (RAW == ';') {
919             NEXT;
920             if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
921                 entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
922             if (entity == NULL) {
923                 
924                 /*
925                  * [ WFC: Entity Declared ]
926                  * In a document without any DTD, a document with only an
927                  * internal DTD subset which contains no parameter entity
928                  * references, or a document with "standalone='yes'", ...
929                  * ... The declaration of a parameter entity must precede
930                  * any reference to it...
931                  */
932                 if ((ctxt->standalone == 1) ||
933                     ((ctxt->hasExternalSubset == 0) &&
934                      (ctxt->hasPErefs == 0))) {
935                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
936                         ctxt->sax->error(ctxt->userData,
937                          "PEReference: %%%s; not found\n", name);
938                     ctxt->wellFormed = 0;
939                     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
940                 } else {
941                     /*
942                      * [ VC: Entity Declared ]
943                      * In a document with an external subset or external
944                      * parameter entities with "standalone='no'", ...
945                      * ... The declaration of a parameter entity must precede
946                      * any reference to it...
947                      */
948                     if ((!ctxt->disableSAX) &&
949                         (ctxt->validate) && (ctxt->vctxt.error != NULL)) {
950                         ctxt->vctxt.error(ctxt->vctxt.userData,
951                              "PEReference: %%%s; not found\n", name);
952                     } else if ((!ctxt->disableSAX) &&
953                         (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
954                         ctxt->sax->warning(ctxt->userData,
955                          "PEReference: %%%s; not found\n", name);
956                     ctxt->valid = 0;
957                 }
958             } else if (ctxt->input->free != deallocblankswrapper) {
959                     input = xmlNewBlanksWrapperInputStream(ctxt, entity);
960                     xmlPushInput(ctxt, input);
961             } else {
962                 if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
963                     (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
964                     xmlChar start[4];
965                     xmlCharEncoding enc;
966
967                     /*
968                      * handle the extra spaces added before and after
969                      * c.f. http://www.w3.org/TR/REC-xml#as-PE
970                      * this is done independently.
971                      */
972                     input = xmlNewEntityInputStream(ctxt, entity);
973                     xmlPushInput(ctxt, input);
974
975                     /* 
976                      * Get the 4 first bytes and decode the charset
977                      * if enc != XML_CHAR_ENCODING_NONE
978                      * plug some encoding conversion routines.
979                      */
980                     GROW
981                     if (entity->length >= 4) {
982                         start[0] = RAW;
983                         start[1] = NXT(1);
984                         start[2] = NXT(2);
985                         start[3] = NXT(3);
986                         enc = xmlDetectCharEncoding(start, 4);
987                         if (enc != XML_CHAR_ENCODING_NONE) {
988                             xmlSwitchEncoding(ctxt, enc);
989                         }
990                     }
991
992                     if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
993                         (RAW == '<') && (NXT(1) == '?') &&
994                         (NXT(2) == 'x') && (NXT(3) == 'm') &&
995                         (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
996                         xmlParseTextDecl(ctxt);
997                     }
998                 } else {
999                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1000                         ctxt->sax->error(ctxt->userData,
1001                          "xmlParserHandlePEReference: %s is not a parameter entity\n",
1002                                          name);
1003                     ctxt->wellFormed = 0;
1004                     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1005                 }
1006             }
1007         } else {
1008             ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
1009             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1010                 ctxt->sax->error(ctxt->userData,
1011                                  "xmlParserHandlePEReference: expecting ';'\n");
1012             ctxt->wellFormed = 0;
1013             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1014         }
1015         xmlFree(name);
1016     }
1017 }
1018
1019 /*
1020  * Macro used to grow the current buffer.
1021  */
1022 #define growBuffer(buffer) {                                            \
1023     buffer##_size *= 2;                                                 \
1024     buffer = (xmlChar *)                                                \
1025                 xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
1026     if (buffer == NULL) {                                               \
1027         xmlGenericError(xmlGenericErrorContext, "realloc failed");      \
1028         return(NULL);                                                   \
1029     }                                                                   \
1030 }
1031
1032 /**
1033  * xmlStringDecodeEntities:
1034  * @ctxt:  the parser context
1035  * @str:  the input string
1036  * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1037  * @end:  an end marker xmlChar, 0 if none
1038  * @end2:  an end marker xmlChar, 0 if none
1039  * @end3:  an end marker xmlChar, 0 if none
1040  * 
1041  * Takes a entity string content and process to do the adequate substitutions.
1042  *
1043  * [67] Reference ::= EntityRef | CharRef
1044  *
1045  * [69] PEReference ::= '%' Name ';'
1046  *
1047  * Returns A newly allocated string with the substitution done. The caller
1048  *      must deallocate it !
1049  */
1050 xmlChar *
1051 xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
1052                         xmlChar end, xmlChar  end2, xmlChar end3) {
1053     xmlChar *buffer = NULL;
1054     int buffer_size = 0;
1055
1056     xmlChar *current = NULL;
1057     xmlEntityPtr ent;
1058     int c,l;
1059     int nbchars = 0;
1060
1061     if (str == NULL)
1062         return(NULL);
1063
1064     if (ctxt->depth > 40) {
1065         ctxt->errNo = XML_ERR_ENTITY_LOOP;
1066         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1067             ctxt->sax->error(ctxt->userData,
1068                 "Detected entity reference loop\n");
1069         ctxt->wellFormed = 0;
1070         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1071         return(NULL);
1072     }
1073
1074     /*
1075      * allocate a translation buffer.
1076      */
1077     buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
1078     buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
1079     if (buffer == NULL) {
1080         xmlGenericError(xmlGenericErrorContext,
1081                         "xmlStringDecodeEntities: malloc failed");
1082         return(NULL);
1083     }
1084
1085     /*
1086      * OK loop until we reach one of the ending char or a size limit.
1087      * we are operating on already parsed values.
1088      */
1089     c = CUR_SCHAR(str, l);
1090     while ((c != 0) && (c != end) && /* non input consuming loop */
1091            (c != end2) && (c != end3)) {
1092
1093         if (c == 0) break;
1094         if ((c == '&') && (str[1] == '#')) {
1095             int val = xmlParseStringCharRef(ctxt, &str);
1096             if (val != 0) {
1097                 COPY_BUF(0,buffer,nbchars,val);
1098             }
1099         } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
1100             if (xmlParserDebugEntities)
1101                 xmlGenericError(xmlGenericErrorContext,
1102                         "String decoding Entity Reference: %.30s\n",
1103                         str);
1104             ent = xmlParseStringEntityRef(ctxt, &str);
1105             if ((ent != NULL) &&
1106                 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1107                 if (ent->content != NULL) {
1108                     COPY_BUF(0,buffer,nbchars,ent->content[0]);
1109                 } else {
1110                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1111                         ctxt->sax->error(ctxt->userData,
1112                             "internal error entity has no content\n");
1113                 }
1114             } else if ((ent != NULL) && (ent->content != NULL)) {
1115                 xmlChar *rep;
1116
1117                 ctxt->depth++;
1118                 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
1119                                               0, 0, 0);
1120                 ctxt->depth--;
1121                 if (rep != NULL) {
1122                     current = rep;
1123                     while (*current != 0) { /* non input consuming loop */
1124                         buffer[nbchars++] = *current++;
1125                         if (nbchars >
1126                             buffer_size - XML_PARSER_BUFFER_SIZE) {
1127                             growBuffer(buffer);
1128                         }
1129                     }
1130                     xmlFree(rep);
1131                 }
1132             } else if (ent != NULL) {
1133                 int i = xmlStrlen(ent->name);
1134                 const xmlChar *cur = ent->name;
1135
1136                 buffer[nbchars++] = '&';
1137                 if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
1138                     growBuffer(buffer);
1139                 }
1140                 for (;i > 0;i--)
1141                     buffer[nbchars++] = *cur++;
1142                 buffer[nbchars++] = ';';
1143             }
1144         } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
1145             if (xmlParserDebugEntities)
1146                 xmlGenericError(xmlGenericErrorContext,
1147                         "String decoding PE Reference: %.30s\n", str);
1148             ent = xmlParseStringPEReference(ctxt, &str);
1149             if (ent != NULL) {
1150                 xmlChar *rep;
1151
1152                 ctxt->depth++;
1153                 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
1154                                               0, 0, 0);
1155                 ctxt->depth--;
1156                 if (rep != NULL) {
1157                     current = rep;
1158                     while (*current != 0) { /* non input consuming loop */
1159                         buffer[nbchars++] = *current++;
1160                         if (nbchars >
1161                             buffer_size - XML_PARSER_BUFFER_SIZE) {
1162                             growBuffer(buffer);
1163                         }
1164                     }
1165                     xmlFree(rep);
1166                 }
1167             }
1168         } else {
1169             COPY_BUF(l,buffer,nbchars,c);
1170             str += l;
1171             if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
1172               growBuffer(buffer);
1173             }
1174         }
1175         c = CUR_SCHAR(str, l);
1176     }
1177     buffer[nbchars++] = 0;
1178     return(buffer);
1179 }
1180
1181
1182 /************************************************************************
1183  *                                                                      *
1184  *              Commodity functions to handle xmlChars                  *
1185  *                                                                      *
1186  ************************************************************************/
1187
1188 /**
1189  * xmlStrndup:
1190  * @cur:  the input xmlChar *
1191  * @len:  the len of @cur
1192  *
1193  * a strndup for array of xmlChar's
1194  *
1195  * Returns a new xmlChar * or NULL
1196  */
1197 xmlChar *
1198 xmlStrndup(const xmlChar *cur, int len) {
1199     xmlChar *ret;
1200     
1201     if ((cur == NULL) || (len < 0)) return(NULL);
1202     ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
1203     if (ret == NULL) {
1204         xmlGenericError(xmlGenericErrorContext,
1205                 "malloc of %ld byte failed\n",
1206                 (len + 1) * (long)sizeof(xmlChar));
1207         return(NULL);
1208     }
1209     memcpy(ret, cur, len * sizeof(xmlChar));
1210     ret[len] = 0;
1211     return(ret);
1212 }
1213
1214 /**
1215  * xmlStrdup:
1216  * @cur:  the input xmlChar *
1217  *
1218  * a strdup for array of xmlChar's. Since they are supposed to be
1219  * encoded in UTF-8 or an encoding with 8bit based chars, we assume
1220  * a termination mark of '0'.
1221  *
1222  * Returns a new xmlChar * or NULL
1223  */
1224 xmlChar *
1225 xmlStrdup(const xmlChar *cur) {
1226     const xmlChar *p = cur;
1227
1228     if (cur == NULL) return(NULL);
1229     while (*p != 0) p++; /* non input consuming */
1230     return(xmlStrndup(cur, p - cur));
1231 }
1232
1233 /**
1234  * xmlCharStrndup:
1235  * @cur:  the input char *
1236  * @len:  the len of @cur
1237  *
1238  * a strndup for char's to xmlChar's
1239  *
1240  * Returns a new xmlChar * or NULL
1241  */
1242
1243 xmlChar *
1244 xmlCharStrndup(const char *cur, int len) {
1245     int i;
1246     xmlChar *ret;
1247     
1248     if ((cur == NULL) || (len < 0)) return(NULL);
1249     ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
1250     if (ret == NULL) {
1251         xmlGenericError(xmlGenericErrorContext, "malloc of %ld byte failed\n",
1252                 (len + 1) * (long)sizeof(xmlChar));
1253         return(NULL);
1254     }
1255     for (i = 0;i < len;i++)
1256         ret[i] = (xmlChar) cur[i];
1257     ret[len] = 0;
1258     return(ret);
1259 }
1260
1261 /**
1262  * xmlCharStrdup:
1263  * @cur:  the input char *
1264  *
1265  * a strdup for char's to xmlChar's
1266  *
1267  * Returns a new xmlChar * or NULL
1268  */
1269
1270 xmlChar *
1271 xmlCharStrdup(const char *cur) {
1272     const char *p = cur;
1273
1274     if (cur == NULL) return(NULL);
1275     while (*p != '\0') p++; /* non input consuming */
1276     return(xmlCharStrndup(cur, p - cur));
1277 }
1278
1279 /**
1280  * xmlStrcmp:
1281  * @str1:  the first xmlChar *
1282  * @str2:  the second xmlChar *
1283  *
1284  * a strcmp for xmlChar's
1285  *
1286  * Returns the integer result of the comparison
1287  */
1288
1289 int
1290 xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
1291     register int tmp;
1292
1293     if (str1 == str2) return(0);
1294     if (str1 == NULL) return(-1);
1295     if (str2 == NULL) return(1);
1296     do {
1297         tmp = *str1++ - *str2;
1298         if (tmp != 0) return(tmp);
1299     } while (*str2++ != 0);
1300     return 0;
1301 }
1302
1303 /**
1304  * xmlStrEqual:
1305  * @str1:  the first xmlChar *
1306  * @str2:  the second xmlChar *
1307  *
1308  * Check if both string are equal of have same content
1309  * Should be a bit more readable and faster than xmlStrEqual()
1310  *
1311  * Returns 1 if they are equal, 0 if they are different
1312  */
1313
1314 int
1315 xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
1316     if (str1 == str2) return(1);
1317     if (str1 == NULL) return(0);
1318     if (str2 == NULL) return(0);
1319     do {
1320         if (*str1++ != *str2) return(0);
1321     } while (*str2++);
1322     return(1);
1323 }
1324
1325 /**
1326  * xmlStrncmp:
1327  * @str1:  the first xmlChar *
1328  * @str2:  the second xmlChar *
1329  * @len:  the max comparison length
1330  *
1331  * a strncmp for xmlChar's
1332  *
1333  * Returns the integer result of the comparison
1334  */
1335
1336 int
1337 xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
1338     register int tmp;
1339
1340     if (len <= 0) return(0);
1341     if (str1 == str2) return(0);
1342     if (str1 == NULL) return(-1);
1343     if (str2 == NULL) return(1);
1344     do {
1345         tmp = *str1++ - *str2;
1346         if (tmp != 0 || --len == 0) return(tmp);
1347     } while (*str2++ != 0);
1348     return 0;
1349 }
1350
1351 static const xmlChar casemap[256] = {
1352     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1353     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
1354     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
1355     0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
1356     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
1357     0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
1358     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
1359     0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
1360     0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
1361     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
1362     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
1363     0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
1364     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
1365     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
1366     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
1367     0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
1368     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
1369     0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
1370     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
1371     0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
1372     0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1373     0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
1374     0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
1375     0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
1376     0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
1377     0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
1378     0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
1379     0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
1380     0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
1381     0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
1382     0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
1383     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
1384 };
1385
1386 /**
1387  * xmlStrcasecmp:
1388  * @str1:  the first xmlChar *
1389  * @str2:  the second xmlChar *
1390  *
1391  * a strcasecmp for xmlChar's
1392  *
1393  * Returns the integer result of the comparison
1394  */
1395
1396 int
1397 xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) {
1398     register int tmp;
1399
1400     if (str1 == str2) return(0);
1401     if (str1 == NULL) return(-1);
1402     if (str2 == NULL) return(1);
1403     do {
1404         tmp = casemap[*str1++] - casemap[*str2];
1405         if (tmp != 0) return(tmp);
1406     } while (*str2++ != 0);
1407     return 0;
1408 }
1409
1410 /**
1411  * xmlStrncasecmp:
1412  * @str1:  the first xmlChar *
1413  * @str2:  the second xmlChar *
1414  * @len:  the max comparison length
1415  *
1416  * a strncasecmp for xmlChar's
1417  *
1418  * Returns the integer result of the comparison
1419  */
1420
1421 int
1422 xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) {
1423     register int tmp;
1424
1425     if (len <= 0) return(0);
1426     if (str1 == str2) return(0);
1427     if (str1 == NULL) return(-1);
1428     if (str2 == NULL) return(1);
1429     do {
1430         tmp = casemap[*str1++] - casemap[*str2];
1431         if (tmp != 0 || --len == 0) return(tmp);
1432     } while (*str2++ != 0);
1433     return 0;
1434 }
1435
1436 /**
1437  * xmlStrchr:
1438  * @str:  the xmlChar * array
1439  * @val:  the xmlChar to search
1440  *
1441  * a strchr for xmlChar's
1442  *
1443  * Returns the xmlChar * for the first occurrence or NULL.
1444  */
1445
1446 const xmlChar *
1447 xmlStrchr(const xmlChar *str, xmlChar val) {
1448     if (str == NULL) return(NULL);
1449     while (*str != 0) { /* non input consuming */
1450         if (*str == val) return((xmlChar *) str);
1451         str++;
1452     }
1453     return(NULL);
1454 }
1455
1456 /**
1457  * xmlStrstr:
1458  * @str:  the xmlChar * array (haystack)
1459  * @val:  the xmlChar to search (needle)
1460  *
1461  * a strstr for xmlChar's
1462  *
1463  * Returns the xmlChar * for the first occurrence or NULL.
1464  */
1465
1466 const xmlChar *
1467 xmlStrstr(const xmlChar *str, const xmlChar *val) {
1468     int n;
1469     
1470     if (str == NULL) return(NULL);
1471     if (val == NULL) return(NULL);
1472     n = xmlStrlen(val);
1473
1474     if (n == 0) return(str);
1475     while (*str != 0) { /* non input consuming */
1476         if (*str == *val) {
1477             if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
1478         }
1479         str++;
1480     }
1481     return(NULL);
1482 }
1483
1484 /**
1485  * xmlStrcasestr:
1486  * @str:  the xmlChar * array (haystack)
1487  * @val:  the xmlChar to search (needle)
1488  *
1489  * a case-ignoring strstr for xmlChar's
1490  *
1491  * Returns the xmlChar * for the first occurrence or NULL.
1492  */
1493
1494 const xmlChar *
1495 xmlStrcasestr(const xmlChar *str, xmlChar *val) {
1496     int n;
1497     
1498     if (str == NULL) return(NULL);
1499     if (val == NULL) return(NULL);
1500     n = xmlStrlen(val);
1501
1502     if (n == 0) return(str);
1503     while (*str != 0) { /* non input consuming */
1504         if (casemap[*str] == casemap[*val])
1505             if (!xmlStrncasecmp(str, val, n)) return(str);
1506         str++;
1507     }
1508     return(NULL);
1509 }
1510
1511 /**
1512  * xmlStrsub:
1513  * @str:  the xmlChar * array (haystack)
1514  * @start:  the index of the first char (zero based)
1515  * @len:  the length of the substring
1516  *
1517  * Extract a substring of a given string
1518  *
1519  * Returns the xmlChar * for the first occurrence or NULL.
1520  */
1521
1522 xmlChar *
1523 xmlStrsub(const xmlChar *str, int start, int len) {
1524     int i;
1525     
1526     if (str == NULL) return(NULL);
1527     if (start < 0) return(NULL);
1528     if (len < 0) return(NULL);
1529
1530     for (i = 0;i < start;i++) {
1531         if (*str == 0) return(NULL);
1532         str++;
1533     }
1534     if (*str == 0) return(NULL);
1535     return(xmlStrndup(str, len));
1536 }
1537
1538 /**
1539  * xmlStrlen:
1540  * @str:  the xmlChar * array
1541  *
1542  * length of a xmlChar's string
1543  *
1544  * Returns the number of xmlChar contained in the ARRAY.
1545  */
1546
1547 int
1548 xmlStrlen(const xmlChar *str) {
1549     int len = 0;
1550
1551     if (str == NULL) return(0);
1552     while (*str != 0) { /* non input consuming */
1553         str++;
1554         len++;
1555     }
1556     return(len);
1557 }
1558
1559 /**
1560  * xmlStrncat:
1561  * @cur:  the original xmlChar * array
1562  * @add:  the xmlChar * array added
1563  * @len:  the length of @add
1564  *
1565  * a strncat for array of xmlChar's, it will extend @cur with the len
1566  * first bytes of @add.
1567  *
1568  * Returns a new xmlChar *, the original @cur is reallocated if needed
1569  * and should not be freed
1570  */
1571
1572 xmlChar *
1573 xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
1574     int size;
1575     xmlChar *ret;
1576
1577     if ((add == NULL) || (len == 0))
1578         return(cur);
1579     if (cur == NULL)
1580         return(xmlStrndup(add, len));
1581
1582     size = xmlStrlen(cur);
1583     ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
1584     if (ret == NULL) {
1585         xmlGenericError(xmlGenericErrorContext,
1586                 "xmlStrncat: realloc of %ld byte failed\n",
1587                 (size + len + 1) * (long)sizeof(xmlChar));
1588         return(cur);
1589     }
1590     memcpy(&ret[size], add, len * sizeof(xmlChar));
1591     ret[size + len] = 0;
1592     return(ret);
1593 }
1594
1595 /**
1596  * xmlStrcat:
1597  * @cur:  the original xmlChar * array
1598  * @add:  the xmlChar * array added
1599  *
1600  * a strcat for array of xmlChar's. Since they are supposed to be
1601  * encoded in UTF-8 or an encoding with 8bit based chars, we assume
1602  * a termination mark of '0'.
1603  *
1604  * Returns a new xmlChar * containing the concatenated string.
1605  */
1606 xmlChar *
1607 xmlStrcat(xmlChar *cur, const xmlChar *add) {
1608     const xmlChar *p = add;
1609
1610     if (add == NULL) return(cur);
1611     if (cur == NULL) 
1612         return(xmlStrdup(add));
1613
1614     while (*p != 0) p++; /* non input consuming */
1615     return(xmlStrncat(cur, add, p - add));
1616 }
1617
1618 /************************************************************************
1619  *                                                                      *
1620  *              Commodity functions, cleanup needed ?                   *
1621  *                                                                      *
1622  ************************************************************************/
1623
1624 /**
1625  * areBlanks:
1626  * @ctxt:  an XML parser context
1627  * @str:  a xmlChar *
1628  * @len:  the size of @str
1629  *
1630  * Is this a sequence of blank chars that one can ignore ?
1631  *
1632  * Returns 1 if ignorable 0 otherwise.
1633  */
1634
1635 static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1636     int i, ret;
1637     xmlNodePtr lastChild;
1638
1639     /*
1640      * Don't spend time trying to differentiate them, the same callback is
1641      * used !
1642      */
1643     if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
1644         return(0);
1645
1646     /*
1647      * Check for xml:space value.
1648      */
1649     if (*(ctxt->space) == 1)
1650         return(0);
1651
1652     /*
1653      * Check that the string is made of blanks
1654      */
1655     for (i = 0;i < len;i++)
1656         if (!(IS_BLANK(str[i]))) return(0);
1657
1658     /*
1659      * Look if the element is mixed content in the DTD if available
1660      */
1661     if (ctxt->node == NULL) return(0);
1662     if (ctxt->myDoc != NULL) {
1663         ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
1664         if (ret == 0) return(1);
1665         if (ret == 1) return(0);
1666     }
1667
1668     /*
1669      * Otherwise, heuristic :-\
1670      */
1671     if (RAW != '<') return(0);
1672     if ((ctxt->node->children == NULL) &&
1673         (RAW == '<') && (NXT(1) == '/')) return(0);
1674
1675     lastChild = xmlGetLastChild(ctxt->node);
1676     if (lastChild == NULL) {
1677         if ((ctxt->node->type != XML_ELEMENT_NODE) &&
1678             (ctxt->node->content != NULL)) return(0);
1679     } else if (xmlNodeIsText(lastChild))
1680         return(0);
1681     else if ((ctxt->node->children != NULL) &&
1682              (xmlNodeIsText(ctxt->node->children)))
1683         return(0);
1684     return(1);
1685 }
1686
1687 /************************************************************************
1688  *                                                                      *
1689  *              Extra stuff for namespace support                       *
1690  *      Relates to http://www.w3.org/TR/WD-xml-names                    *
1691  *                                                                      *
1692  ************************************************************************/
1693
1694 /**
1695  * xmlSplitQName:
1696  * @ctxt:  an XML parser context
1697  * @name:  an XML parser context
1698  * @prefix:  a xmlChar ** 
1699  *
1700  * parse an UTF8 encoded XML qualified name string
1701  *
1702  * [NS 5] QName ::= (Prefix ':')? LocalPart
1703  *
1704  * [NS 6] Prefix ::= NCName
1705  *
1706  * [NS 7] LocalPart ::= NCName
1707  *
1708  * Returns the local part, and prefix is updated
1709  *   to get the Prefix if any.
1710  */
1711
1712 xmlChar *
1713 xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
1714     xmlChar buf[XML_MAX_NAMELEN + 5];
1715     xmlChar *buffer = NULL;
1716     int len = 0;
1717     int max = XML_MAX_NAMELEN;
1718     xmlChar *ret = NULL;
1719     const xmlChar *cur = name;
1720     int c;
1721
1722     *prefix = NULL;
1723
1724     if (cur == NULL) return(NULL);
1725
1726 #ifndef XML_XML_NAMESPACE
1727     /* xml: prefix is not really a namespace */
1728     if ((cur[0] == 'x') && (cur[1] == 'm') &&
1729         (cur[2] == 'l') && (cur[3] == ':'))
1730         return(xmlStrdup(name));
1731 #endif
1732
1733     /* nasty but well=formed */
1734     if (cur[0] == ':')
1735         return(xmlStrdup(name));
1736
1737     c = *cur++;
1738     while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
1739         buf[len++] = c;
1740         c = *cur++;
1741     }
1742     if (len >= max) {
1743         /*
1744          * Okay someone managed to make a huge name, so he's ready to pay
1745          * for the processing speed.
1746          */
1747         max = len * 2;
1748         
1749         buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
1750         if (buffer == NULL) {
1751             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1752                 ctxt->sax->error(ctxt->userData,
1753                                  "xmlSplitQName: out of memory\n");
1754             return(NULL);
1755         }
1756         memcpy(buffer, buf, len);
1757         while ((c != 0) && (c != ':')) { /* tested bigname.xml */
1758             if (len + 10 > max) {
1759                 max *= 2;
1760                 buffer = (xmlChar *) xmlRealloc(buffer,
1761                                                 max * sizeof(xmlChar));
1762                 if (buffer == NULL) {
1763                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1764                         ctxt->sax->error(ctxt->userData,
1765                                          "xmlSplitQName: out of memory\n");
1766                     return(NULL);
1767                 }
1768             }
1769             buffer[len++] = c;
1770             c = *cur++;
1771         }
1772         buffer[len] = 0;
1773     }
1774     
1775     /* nasty but well=formed
1776     if ((c == ':') && (*cur == 0)) {
1777         return(xmlStrdup(name));
1778     } */
1779
1780     if (buffer == NULL)
1781         ret = xmlStrndup(buf, len);
1782     else {
1783         ret = buffer;
1784         buffer = NULL;
1785         max = XML_MAX_NAMELEN;
1786     }
1787
1788
1789     if (c == ':') {
1790         c = *cur;
1791         *prefix = ret;
1792         if (c == 0) {
1793             return(xmlStrndup(BAD_CAST "", 0));
1794         }
1795         len = 0;
1796
1797         /*
1798          * Check that the first character is proper to start
1799          * a new name
1800          */
1801         if (!(((c >= 0x61) && (c <= 0x7A)) ||
1802               ((c >= 0x41) && (c <= 0x5A)) ||
1803               (c == '_') || (c == ':'))) {
1804             int l;
1805             int first = CUR_SCHAR(cur, l);
1806
1807             if (!IS_LETTER(first) && (first != '_')) {
1808                 if ((ctxt != NULL) && (ctxt->sax != NULL) &&
1809                     (ctxt->sax->error != NULL))
1810                     ctxt->sax->error(ctxt->userData,
1811                             "Name %s is not XML Namespace compliant\n",
1812                                      name);
1813             }
1814         }
1815         cur++;
1816
1817         while ((c != 0) && (len < max)) { /* tested bigname2.xml */
1818             buf[len++] = c;
1819             c = *cur++;
1820         }
1821         if (len >= max) {
1822             /*
1823              * Okay someone managed to make a huge name, so he's ready to pay
1824              * for the processing speed.
1825              */
1826             max = len * 2;
1827             
1828             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
1829             if (buffer == NULL) {
1830                 if ((ctxt != NULL) && (ctxt->sax != NULL) &&
1831                     (ctxt->sax->error != NULL))
1832                     ctxt->sax->error(ctxt->userData,
1833                                      "xmlSplitQName: out of memory\n");
1834                 return(NULL);
1835             }
1836             memcpy(buffer, buf, len);
1837             while (c != 0) { /* tested bigname2.xml */
1838                 if (len + 10 > max) {
1839                     max *= 2;
1840                     buffer = (xmlChar *) xmlRealloc(buffer,
1841                                                     max * sizeof(xmlChar));
1842                     if (buffer == NULL) {
1843                         if ((ctxt != NULL) && (ctxt->sax != NULL) &&
1844                             (ctxt->sax->error != NULL))
1845                             ctxt->sax->error(ctxt->userData,
1846                                              "xmlSplitQName: out of memory\n");
1847                         return(NULL);
1848                     }
1849                 }
1850                 buffer[len++] = c;
1851                 c = *cur++;
1852             }
1853             buffer[len] = 0;
1854         }
1855         
1856         if (buffer == NULL)
1857             ret = xmlStrndup(buf, len);
1858         else {
1859             ret = buffer;
1860         }
1861     }
1862
1863     return(ret);
1864 }
1865
1866 /************************************************************************
1867  *                                                                      *
1868  *                      The parser itself                               *
1869  *      Relates to http://www.w3.org/TR/REC-xml                         *
1870  *                                                                      *
1871  ************************************************************************/
1872
1873 static xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt);
1874 /**
1875  * xmlParseName:
1876  * @ctxt:  an XML parser context
1877  *
1878  * parse an XML name.
1879  *
1880  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1881  *                  CombiningChar | Extender
1882  *
1883  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1884  *
1885  * [6] Names ::= Name (S Name)*
1886  *
1887  * Returns the Name parsed or NULL
1888  */
1889
1890 xmlChar *
1891 xmlParseName(xmlParserCtxtPtr ctxt) {
1892     const xmlChar *in;
1893     xmlChar *ret;
1894     int count = 0;
1895
1896     GROW;
1897
1898     /*
1899      * Accelerator for simple ASCII names
1900      */
1901     in = ctxt->input->cur;
1902     if (((*in >= 0x61) && (*in <= 0x7A)) ||
1903         ((*in >= 0x41) && (*in <= 0x5A)) ||
1904         (*in == '_') || (*in == ':')) {
1905         in++;
1906         while (((*in >= 0x61) && (*in <= 0x7A)) ||
1907                ((*in >= 0x41) && (*in <= 0x5A)) ||
1908                ((*in >= 0x30) && (*in <= 0x39)) ||
1909                (*in == '_') || (*in == '-') ||
1910                (*in == ':') || (*in == '.'))
1911             in++;
1912         if ((*in > 0) && (*in < 0x80)) {
1913             count = in - ctxt->input->cur;
1914             ret = xmlStrndup(ctxt->input->cur, count);
1915             ctxt->input->cur = in;
1916             ctxt->nbChars += count;
1917             ctxt->input->col += count;
1918             if (ret == NULL) {
1919                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1920                     ctxt->sax->error(ctxt->userData, 
1921                          "XML parser: out of memory\n");
1922                 ctxt->errNo = XML_ERR_NO_MEMORY;
1923                 ctxt->instate = XML_PARSER_EOF;
1924                 ctxt->disableSAX = 1;
1925             }
1926             return(ret);
1927         }
1928     }
1929     return(xmlParseNameComplex(ctxt));
1930 }
1931
1932 /**
1933  * xmlParseNameAndCompare:
1934  * @ctxt:  an XML parser context
1935  *
1936  * parse an XML name and compares for match
1937  * (specialized for endtag parsing)
1938  *
1939  *
1940  * Returns NULL for an illegal name, (xmlChar*) 1 for success
1941  * and the name for mismatch
1942  */
1943
1944 static xmlChar *
1945 xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
1946     const xmlChar *cmp = other;
1947     const xmlChar *in;
1948     xmlChar *ret;
1949
1950     GROW;
1951     
1952     in = ctxt->input->cur;
1953     while (*in != 0 && *in == *cmp) {
1954         ++in;
1955         ++cmp;
1956     }
1957     if (*cmp == 0 && (*in == '>' || IS_BLANK (*in))) {
1958         /* success */
1959         ctxt->input->cur = in;
1960         return (xmlChar*) 1;
1961     }
1962     /* failure (or end of input buffer), check with full function */
1963     ret = xmlParseName (ctxt);
1964     if (ret != 0 && xmlStrEqual (ret, other)) {
1965         xmlFree (ret);
1966         return (xmlChar*) 1;
1967     }
1968     return ret;
1969 }
1970
1971 static xmlChar *
1972 xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
1973     xmlChar buf[XML_MAX_NAMELEN + 5];
1974     int len = 0, l;
1975     int c;
1976     int count = 0;
1977
1978     /*
1979      * Handler for more complex cases
1980      */
1981     GROW;
1982     c = CUR_CHAR(l);
1983     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
1984         (!IS_LETTER(c) && (c != '_') &&
1985          (c != ':'))) {
1986         return(NULL);
1987     }
1988
1989     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
1990            ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
1991             (c == '.') || (c == '-') ||
1992             (c == '_') || (c == ':') || 
1993             (IS_COMBINING(c)) ||
1994             (IS_EXTENDER(c)))) {
1995         if (count++ > 100) {
1996             count = 0;
1997             GROW;
1998         }
1999         COPY_BUF(l,buf,len,c);
2000         NEXTL(l);
2001         c = CUR_CHAR(l);
2002         if (len >= XML_MAX_NAMELEN) {
2003             /*
2004              * Okay someone managed to make a huge name, so he's ready to pay
2005              * for the processing speed.
2006              */
2007             xmlChar *buffer;
2008             int max = len * 2;
2009             
2010             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2011             if (buffer == NULL) {
2012                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2013                     ctxt->sax->error(ctxt->userData,
2014                                      "xmlParseNameComplex: out of memory\n");
2015                 return(NULL);
2016             }
2017             memcpy(buffer, buf, len);
2018             while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
2019                    (c == '.') || (c == '-') ||
2020                    (c == '_') || (c == ':') || 
2021                    (IS_COMBINING(c)) ||
2022                    (IS_EXTENDER(c))) {
2023                 if (count++ > 100) {
2024                     count = 0;
2025                     GROW;
2026                 }
2027                 if (len + 10 > max) {
2028                     max *= 2;
2029                     buffer = (xmlChar *) xmlRealloc(buffer,
2030                                                     max * sizeof(xmlChar));
2031                     if (buffer == NULL) {
2032                         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2033                             ctxt->sax->error(ctxt->userData,
2034                                      "xmlParseNameComplex: out of memory\n");
2035                         return(NULL);
2036                     }
2037                 }
2038                 COPY_BUF(l,buffer,len,c);
2039                 NEXTL(l);
2040                 c = CUR_CHAR(l);
2041             }
2042             buffer[len] = 0;
2043             return(buffer);
2044         }
2045     }
2046     return(xmlStrndup(buf, len));
2047 }
2048
2049 /**
2050  * xmlParseStringName:
2051  * @ctxt:  an XML parser context
2052  * @str:  a pointer to the string pointer (IN/OUT)
2053  *
2054  * parse an XML name.
2055  *
2056  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
2057  *                  CombiningChar | Extender
2058  *
2059  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
2060  *
2061  * [6] Names ::= Name (S Name)*
2062  *
2063  * Returns the Name parsed or NULL. The @str pointer 
2064  * is updated to the current location in the string.
2065  */
2066
2067 static xmlChar *
2068 xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
2069     xmlChar buf[XML_MAX_NAMELEN + 5];
2070     const xmlChar *cur = *str;
2071     int len = 0, l;
2072     int c;
2073
2074     c = CUR_SCHAR(cur, l);
2075     if (!IS_LETTER(c) && (c != '_') &&
2076         (c != ':')) {
2077         return(NULL);
2078     }
2079
2080     while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */
2081            (c == '.') || (c == '-') ||
2082            (c == '_') || (c == ':') || 
2083            (IS_COMBINING(c)) ||
2084            (IS_EXTENDER(c))) {
2085         COPY_BUF(l,buf,len,c);
2086         cur += l;
2087         c = CUR_SCHAR(cur, l);
2088         if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
2089             /*
2090              * Okay someone managed to make a huge name, so he's ready to pay
2091              * for the processing speed.
2092              */
2093             xmlChar *buffer;
2094             int max = len * 2;
2095             
2096             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2097             if (buffer == NULL) {
2098                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2099                     ctxt->sax->error(ctxt->userData,
2100                                      "xmlParseStringName: out of memory\n");
2101                 return(NULL);
2102             }
2103             memcpy(buffer, buf, len);
2104             while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */
2105                    (c == '.') || (c == '-') ||
2106                    (c == '_') || (c == ':') || 
2107                    (IS_COMBINING(c)) ||
2108                    (IS_EXTENDER(c))) {
2109                 if (len + 10 > max) {
2110                     max *= 2;
2111                     buffer = (xmlChar *) xmlRealloc(buffer,
2112                                                     max * sizeof(xmlChar));
2113                     if (buffer == NULL) {
2114                         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2115                             ctxt->sax->error(ctxt->userData,
2116                                      "xmlParseStringName: out of memory\n");
2117                         return(NULL);
2118                     }
2119                 }
2120                 COPY_BUF(l,buffer,len,c);
2121                 cur += l;
2122                 c = CUR_SCHAR(cur, l);
2123             }
2124             buffer[len] = 0;
2125             *str = cur;
2126             return(buffer);
2127         }
2128     }
2129     *str = cur;
2130     return(xmlStrndup(buf, len));
2131 }
2132
2133 /**
2134  * xmlParseNmtoken:
2135  * @ctxt:  an XML parser context
2136  * 
2137  * parse an XML Nmtoken.
2138  *
2139  * [7] Nmtoken ::= (NameChar)+
2140  *
2141  * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
2142  *
2143  * Returns the Nmtoken parsed or NULL
2144  */
2145
2146 xmlChar *
2147 xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
2148     xmlChar buf[XML_MAX_NAMELEN + 5];
2149     int len = 0, l;
2150     int c;
2151     int count = 0;
2152
2153     GROW;
2154     c = CUR_CHAR(l);
2155
2156     while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
2157            (c == '.') || (c == '-') ||
2158            (c == '_') || (c == ':') || 
2159            (IS_COMBINING(c)) ||
2160            (IS_EXTENDER(c))) {
2161         if (count++ > 100) {
2162             count = 0;
2163             GROW;
2164         }
2165         COPY_BUF(l,buf,len,c);
2166         NEXTL(l);
2167         c = CUR_CHAR(l);
2168         if (len >= XML_MAX_NAMELEN) {
2169             /*
2170              * Okay someone managed to make a huge token, so he's ready to pay
2171              * for the processing speed.
2172              */
2173             xmlChar *buffer;
2174             int max = len * 2;
2175             
2176             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2177             if (buffer == NULL) {
2178                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2179                     ctxt->sax->error(ctxt->userData,
2180                                      "xmlParseNmtoken: out of memory\n");
2181                 return(NULL);
2182             }
2183             memcpy(buffer, buf, len);
2184             while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
2185                    (c == '.') || (c == '-') ||
2186                    (c == '_') || (c == ':') || 
2187                    (IS_COMBINING(c)) ||
2188                    (IS_EXTENDER(c))) {
2189                 if (count++ > 100) {
2190                     count = 0;
2191                     GROW;
2192                 }
2193                 if (len + 10 > max) {
2194                     max *= 2;
2195                     buffer = (xmlChar *) xmlRealloc(buffer,
2196                                                     max * sizeof(xmlChar));
2197                     if (buffer == NULL) {
2198                         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2199                             ctxt->sax->error(ctxt->userData,
2200                                      "xmlParseNmtoken: out of memory\n");
2201                         return(NULL);
2202                     }
2203                 }
2204                 COPY_BUF(l,buffer,len,c);
2205                 NEXTL(l);
2206                 c = CUR_CHAR(l);
2207             }
2208             buffer[len] = 0;
2209             return(buffer);
2210         }
2211     }
2212     if (len == 0)
2213         return(NULL);
2214     return(xmlStrndup(buf, len));
2215 }
2216
2217 /**
2218  * xmlParseEntityValue:
2219  * @ctxt:  an XML parser context
2220  * @orig:  if non-NULL store a copy of the original entity value
2221  *
2222  * parse a value for ENTITY declarations
2223  *
2224  * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
2225  *                     "'" ([^%&'] | PEReference | Reference)* "'"
2226  *
2227  * Returns the EntityValue parsed with reference substituted or NULL
2228  */
2229
2230 xmlChar *
2231 xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
2232     xmlChar *buf = NULL;
2233     int len = 0;
2234     int size = XML_PARSER_BUFFER_SIZE;
2235     int c, l;
2236     xmlChar stop;
2237     xmlChar *ret = NULL;
2238     const xmlChar *cur = NULL;
2239     xmlParserInputPtr input;
2240
2241     if (RAW == '"') stop = '"';
2242     else if (RAW == '\'') stop = '\'';
2243     else {
2244         ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
2245         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2246             ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
2247         ctxt->wellFormed = 0;
2248         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2249         return(NULL);
2250     }
2251     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2252     if (buf == NULL) {
2253         xmlGenericError(xmlGenericErrorContext,
2254                 "malloc of %d byte failed\n", size);
2255         return(NULL);
2256     }
2257
2258     /*
2259      * The content of the entity definition is copied in a buffer.
2260      */
2261
2262     ctxt->instate = XML_PARSER_ENTITY_VALUE;
2263     input = ctxt->input;
2264     GROW;
2265     NEXT;
2266     c = CUR_CHAR(l);
2267     /*
2268      * NOTE: 4.4.5 Included in Literal
2269      * When a parameter entity reference appears in a literal entity
2270      * value, ... a single or double quote character in the replacement
2271      * text is always treated as a normal data character and will not
2272      * terminate the literal. 
2273      * In practice it means we stop the loop only when back at parsing
2274      * the initial entity and the quote is found
2275      */
2276     while ((IS_CHAR(c)) && ((c != stop) || /* checked */
2277            (ctxt->input != input))) {
2278         if (len + 5 >= size) {
2279             size *= 2;
2280             buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2281             if (buf == NULL) {
2282                 xmlGenericError(xmlGenericErrorContext,
2283                         "realloc of %d byte failed\n", size);
2284                 return(NULL);
2285             }
2286         }
2287         COPY_BUF(l,buf,len,c);
2288         NEXTL(l);
2289         /*
2290          * Pop-up of finished entities.
2291          */
2292         while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
2293             xmlPopInput(ctxt);
2294
2295         GROW;
2296         c = CUR_CHAR(l);
2297         if (c == 0) {
2298             GROW;
2299             c = CUR_CHAR(l);
2300         }
2301     }
2302     buf[len] = 0;
2303
2304     /*
2305      * Raise problem w.r.t. '&' and '%' being used in non-entities
2306      * reference constructs. Note Charref will be handled in
2307      * xmlStringDecodeEntities()
2308      */
2309     cur = buf;
2310     while (*cur != 0) { /* non input consuming */
2311         if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
2312             xmlChar *name;
2313             xmlChar tmp = *cur;
2314
2315             cur++;
2316             name = xmlParseStringName(ctxt, &cur);
2317             if ((name == NULL) || (*cur != ';')) {
2318                 ctxt->errNo = XML_ERR_ENTITY_CHAR_ERROR;
2319                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2320                     ctxt->sax->error(ctxt->userData,
2321             "EntityValue: '%c' forbidden except for entities references\n",
2322                                      tmp);
2323                 ctxt->wellFormed = 0;
2324                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2325             }
2326             if ((tmp == '%') && (ctxt->inSubset == 1) &&
2327                 (ctxt->inputNr == 1)) {
2328                 ctxt->errNo = XML_ERR_ENTITY_PE_INTERNAL;
2329                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2330                     ctxt->sax->error(ctxt->userData,
2331             "EntityValue: PEReferences forbidden in internal subset\n",
2332                                      tmp);
2333                 ctxt->wellFormed = 0;
2334                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2335             }
2336             if (name != NULL)
2337                 xmlFree(name);
2338         }
2339         cur++;
2340     }
2341
2342     /*
2343      * Then PEReference entities are substituted.
2344      */
2345     if (c != stop) {
2346         ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
2347         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2348             ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
2349         ctxt->wellFormed = 0;
2350         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2351         xmlFree(buf);
2352     } else {
2353         NEXT;
2354         /*
2355          * NOTE: 4.4.7 Bypassed
2356          * When a general entity reference appears in the EntityValue in
2357          * an entity declaration, it is bypassed and left as is.
2358          * so XML_SUBSTITUTE_REF is not set here.
2359          */
2360         ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
2361                                       0, 0, 0);
2362         if (orig != NULL) 
2363             *orig = buf;
2364         else
2365             xmlFree(buf);
2366     }
2367     
2368     return(ret);
2369 }
2370
2371 /**
2372  * xmlParseAttValue:
2373  * @ctxt:  an XML parser context
2374  *
2375  * parse a value for an attribute
2376  * Note: the parser won't do substitution of entities here, this
2377  * will be handled later in xmlStringGetNodeList
2378  *
2379  * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
2380  *                   "'" ([^<&'] | Reference)* "'"
2381  *
2382  * 3.3.3 Attribute-Value Normalization:
2383  * Before the value of an attribute is passed to the application or
2384  * checked for validity, the XML processor must normalize it as follows: 
2385  * - a character reference is processed by appending the referenced
2386  *   character to the attribute value
2387  * - an entity reference is processed by recursively processing the
2388  *   replacement text of the entity 
2389  * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
2390  *   appending #x20 to the normalized value, except that only a single
2391  *   #x20 is appended for a "#xD#xA" sequence that is part of an external
2392  *   parsed entity or the literal entity value of an internal parsed entity 
2393  * - other characters are processed by appending them to the normalized value 
2394  * If the declared value is not CDATA, then the XML processor must further
2395  * process the normalized attribute value by discarding any leading and
2396  * trailing space (#x20) characters, and by replacing sequences of space
2397  * (#x20) characters by a single space (#x20) character.  
2398  * All attributes for which no declaration has been read should be treated
2399  * by a non-validating parser as if declared CDATA.
2400  *
2401  * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
2402  */
2403
2404 xmlChar *
2405 xmlParseAttValueComplex(xmlParserCtxtPtr ctxt);
2406
2407 xmlChar *
2408 xmlParseAttValue(xmlParserCtxtPtr ctxt) {
2409     xmlChar limit = 0;
2410     const xmlChar *in = NULL;
2411     xmlChar *ret = NULL;
2412     SHRINK;
2413     GROW;
2414     in = (xmlChar *) CUR_PTR;
2415     if (*in != '"' && *in != '\'') {
2416       ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
2417       if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2418           ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
2419       ctxt->wellFormed = 0;
2420       if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2421       return(NULL);
2422     } 
2423     ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
2424     limit = *in;
2425     ++in;
2426     
2427     while (*in != limit && *in >= 0x20 && *in <= 0x7f && 
2428       *in != '&' && *in != '<'
2429     ) {
2430       ++in;
2431     }
2432     if (*in != limit) {
2433       return xmlParseAttValueComplex(ctxt);
2434     }
2435     ++in;
2436     ret = xmlStrndup (CUR_PTR + 1, in - CUR_PTR - 2);
2437     CUR_PTR = in;
2438     return ret;
2439 }
2440
2441 /**
2442  * xmlParseAttValueComplex:
2443  * @ctxt:  an XML parser context
2444  *
2445  * parse a value for an attribute, this is the fallback function
2446  * of xmlParseAttValue() when the attribute parsing requires handling
2447  * of non-ASCII characters.
2448  *
2449  * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
2450  */
2451 xmlChar *
2452 xmlParseAttValueComplex(xmlParserCtxtPtr ctxt) {
2453     xmlChar limit = 0;
2454     xmlChar *buf = NULL;
2455     int len = 0;
2456     int buf_size = 0;
2457     int c, l;
2458     xmlChar *current = NULL;
2459     xmlEntityPtr ent;
2460
2461
2462     SHRINK;
2463     if (NXT(0) == '"') {
2464         ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
2465         limit = '"';
2466         NEXT;
2467     } else if (NXT(0) == '\'') {
2468         limit = '\'';
2469         ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
2470         NEXT;
2471     } else {
2472         ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
2473         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2474             ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
2475         ctxt->wellFormed = 0;
2476         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2477         return(NULL);
2478     }
2479     
2480     /*
2481      * allocate a translation buffer.
2482      */
2483     buf_size = XML_PARSER_BUFFER_SIZE;
2484     buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
2485     if (buf == NULL) {
2486         xmlGenericError(xmlGenericErrorContext,
2487                         "xmlParseAttValue: malloc failed");
2488         return(NULL);
2489     }
2490
2491     /*
2492      * OK loop until we reach one of the ending char or a size limit.
2493      */
2494     c = CUR_CHAR(l);
2495     while ((NXT(0) != limit) && /* checked */
2496            (c != '<')) {
2497         if (c == 0) break;
2498         if (c == '&') {
2499             if (NXT(1) == '#') {
2500                 int val = xmlParseCharRef(ctxt);
2501                 if (val == '&') {
2502                     if (ctxt->replaceEntities) {
2503                         if (len > buf_size - 10) {
2504                             growBuffer(buf);
2505                         }
2506                         buf[len++] = '&';
2507                     } else {
2508                         /*
2509                          * The reparsing will be done in xmlStringGetNodeList()
2510                          * called by the attribute() function in SAX.c
2511                          */
2512                         static xmlChar buffer[6] = "&#38;";
2513
2514                         if (len > buf_size - 10) {
2515                             growBuffer(buf);
2516                         }
2517                         current = &buffer[0];
2518                         while (*current != 0) { /* non input consuming */
2519                             buf[len++] = *current++;
2520                         }
2521                     }
2522                 } else {
2523                     if (len > buf_size - 10) {
2524                         growBuffer(buf);
2525                     }
2526                     len += xmlCopyChar(0, &buf[len], val);
2527                 }
2528             } else {
2529                 ent = xmlParseEntityRef(ctxt);
2530                 if ((ent != NULL) && 
2531                     (ctxt->replaceEntities != 0)) {
2532                     xmlChar *rep;
2533
2534                     if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
2535                         rep = xmlStringDecodeEntities(ctxt, ent->content,
2536                                                       XML_SUBSTITUTE_REF, 0, 0, 0);
2537                         if (rep != NULL) {
2538                             current = rep;
2539                             while (*current != 0) { /* non input consuming */
2540                                 buf[len++] = *current++;
2541                                 if (len > buf_size - 10) {
2542                                     growBuffer(buf);
2543                                 }
2544                             }
2545                             xmlFree(rep);
2546                         }
2547                     } else {
2548                         if (len > buf_size - 10) {
2549                             growBuffer(buf);
2550                         }
2551                         if (ent->content != NULL)
2552                             buf[len++] = ent->content[0];
2553                     }
2554                 } else if (ent != NULL) {
2555                     int i = xmlStrlen(ent->name);
2556                     const xmlChar *cur = ent->name;
2557
2558                     /*
2559                      * This may look absurd but is needed to detect
2560                      * entities problems
2561                      */
2562                     if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
2563                         (ent->content != NULL)) {
2564                         xmlChar *rep;
2565                         rep = xmlStringDecodeEntities(ctxt, ent->content,
2566                                                       XML_SUBSTITUTE_REF, 0, 0, 0);
2567                         if (rep != NULL)
2568                             xmlFree(rep);
2569                     }
2570
2571                     /*
2572                      * Just output the reference
2573                      */
2574                     buf[len++] = '&';
2575                     if (len > buf_size - i - 10) {
2576                         growBuffer(buf);
2577                     }
2578                     for (;i > 0;i--)
2579                         buf[len++] = *cur++;
2580                     buf[len++] = ';';
2581                 }
2582             }
2583         } else {
2584             if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
2585                 COPY_BUF(l,buf,len,0x20);
2586                 if (len > buf_size - 10) {
2587                     growBuffer(buf);
2588                 }
2589             } else {
2590                 COPY_BUF(l,buf,len,c);
2591                 if (len > buf_size - 10) {
2592                     growBuffer(buf);
2593                 }
2594             }
2595             NEXTL(l);
2596         }
2597         GROW;
2598         c = CUR_CHAR(l);
2599     }
2600     buf[len++] = 0;
2601     if (RAW == '<') {
2602         ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
2603         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2604             ctxt->sax->error(ctxt->userData,
2605                "Unescaped '<' not allowed in attributes values\n");
2606         ctxt->wellFormed = 0;
2607         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2608     } else if (RAW != limit) {
2609         ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
2610         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2611             ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
2612         ctxt->wellFormed = 0;
2613         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2614     } else
2615         NEXT;
2616     return(buf);
2617 }
2618
2619 /**
2620  * xmlParseSystemLiteral:
2621  * @ctxt:  an XML parser context
2622  * 
2623  * parse an XML Literal
2624  *
2625  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
2626  *
2627  * Returns the SystemLiteral parsed or NULL
2628  */
2629
2630 xmlChar *
2631 xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
2632     xmlChar *buf = NULL;
2633     int len = 0;
2634     int size = XML_PARSER_BUFFER_SIZE;
2635     int cur, l;
2636     xmlChar stop;
2637     int state = ctxt->instate;
2638     int count = 0;
2639
2640     SHRINK;
2641     if (RAW == '"') {
2642         NEXT;
2643         stop = '"';
2644     } else if (RAW == '\'') {
2645         NEXT;
2646         stop = '\'';
2647     } else {
2648         ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2649         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2650             ctxt->sax->error(ctxt->userData,
2651                              "SystemLiteral \" or ' expected\n");
2652         ctxt->wellFormed = 0;
2653         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2654         return(NULL);
2655     }
2656     
2657     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2658     if (buf == NULL) {
2659         xmlGenericError(xmlGenericErrorContext,
2660                 "malloc of %d byte failed\n", size);
2661         return(NULL);
2662     }
2663     ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
2664     cur = CUR_CHAR(l);
2665     while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
2666         if (len + 5 >= size) {
2667             size *= 2;
2668             buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2669             if (buf == NULL) {
2670                 xmlGenericError(xmlGenericErrorContext,
2671                         "realloc of %d byte failed\n", size);
2672                 ctxt->instate = (xmlParserInputState) state;
2673                 return(NULL);
2674             }
2675         }
2676         count++;
2677         if (count > 50) {
2678             GROW;
2679             count = 0;
2680         }
2681         COPY_BUF(l,buf,len,cur);
2682         NEXTL(l);
2683         cur = CUR_CHAR(l);
2684         if (cur == 0) {
2685             GROW;
2686             SHRINK;
2687             cur = CUR_CHAR(l);
2688         }
2689     }
2690     buf[len] = 0;
2691     ctxt->instate = (xmlParserInputState) state;
2692     if (!IS_CHAR(cur)) {
2693         ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2694         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2695             ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
2696         ctxt->wellFormed = 0;
2697         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2698     } else {
2699         NEXT;
2700     }
2701     return(buf);
2702 }
2703
2704 /**
2705  * xmlParsePubidLiteral:
2706  * @ctxt:  an XML parser context
2707  *
2708  * parse an XML public literal
2709  *
2710  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2711  *
2712  * Returns the PubidLiteral parsed or NULL.
2713  */
2714
2715 xmlChar *
2716 xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
2717     xmlChar *buf = NULL;
2718     int len = 0;
2719     int size = XML_PARSER_BUFFER_SIZE;
2720     xmlChar cur;
2721     xmlChar stop;
2722     int count = 0;
2723     xmlParserInputState oldstate = ctxt->instate;
2724
2725     SHRINK;
2726     if (RAW == '"') {
2727         NEXT;
2728         stop = '"';
2729     } else if (RAW == '\'') {
2730         NEXT;
2731         stop = '\'';
2732     } else {
2733         ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2734         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2735             ctxt->sax->error(ctxt->userData,
2736                              "SystemLiteral \" or ' expected\n");
2737         ctxt->wellFormed = 0;
2738         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2739         return(NULL);
2740     }
2741     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2742     if (buf == NULL) {
2743         xmlGenericError(xmlGenericErrorContext,
2744                 "malloc of %d byte failed\n", size);
2745         return(NULL);
2746     }
2747     ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
2748     cur = CUR;
2749     while ((IS_PUBIDCHAR(cur)) && (cur != stop)) { /* checked */
2750         if (len + 1 >= size) {
2751             size *= 2;
2752             buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2753             if (buf == NULL) {
2754                 xmlGenericError(xmlGenericErrorContext,
2755                         "realloc of %d byte failed\n", size);
2756                 return(NULL);
2757             }
2758         }
2759         buf[len++] = cur;
2760         count++;
2761         if (count > 50) {
2762             GROW;
2763             count = 0;
2764         }
2765         NEXT;
2766         cur = CUR;
2767         if (cur == 0) {
2768             GROW;
2769             SHRINK;
2770             cur = CUR;
2771         }
2772     }
2773     buf[len] = 0;
2774     if (cur != stop) {
2775         ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2776         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2777             ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
2778         ctxt->wellFormed = 0;
2779         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2780     } else {
2781         NEXT;
2782     }
2783     ctxt->instate = oldstate;
2784     return(buf);
2785 }
2786
2787 void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
2788 /**
2789  * xmlParseCharData:
2790  * @ctxt:  an XML parser context
2791  * @cdata:  int indicating whether we are within a CDATA section
2792  *
2793  * parse a CharData section.
2794  * if we are within a CDATA section ']]>' marks an end of section.
2795  *
2796  * The right angle bracket (>) may be represented using the string "&gt;",
2797  * and must, for compatibility, be escaped using "&gt;" or a character
2798  * reference when it appears in the string "]]>" in content, when that
2799  * string is not marking the end of a CDATA section. 
2800  *
2801  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2802  */
2803
2804 void
2805 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
2806     const xmlChar *in;
2807     int nbchar = 0;
2808     int line = ctxt->input->line;
2809     int col = ctxt->input->col;
2810
2811     SHRINK;
2812     GROW;
2813     /*
2814      * Accelerated common case where input don't need to be
2815      * modified before passing it to the handler.
2816      */
2817     if (!cdata) {
2818         in = ctxt->input->cur;
2819         do {
2820 get_more:
2821             while (((*in >= 0x20) && (*in != '<') && (*in != ']') &&
2822                     (*in != '&') && (*in <= 0x7F)) || (*in == 0x09))
2823                 in++;
2824             if (*in == 0xA) {
2825                 ctxt->input->line++;
2826                 in++;
2827                 while (*in == 0xA) {
2828                     ctxt->input->line++;
2829                     in++;
2830                 }
2831                 goto get_more;
2832             }
2833             if (*in == ']') {
2834                 if ((in[1] == ']') && (in[2] == '>')) {
2835                     ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
2836                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2837                         ctxt->sax->error(ctxt->userData,
2838                            "Sequence ']]>' not allowed in content\n");
2839                     ctxt->input->cur = in;
2840                     ctxt->wellFormed = 0;
2841                     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2842                     return;
2843                 }
2844                 in++;
2845                 goto get_more;
2846             }
2847             nbchar = in - ctxt->input->cur;
2848             if (nbchar > 0) {
2849                 if (IS_BLANK(*ctxt->input->cur)) {
2850                     const xmlChar *tmp = ctxt->input->cur;
2851                     ctxt->input->cur = in;
2852                     if (areBlanks(ctxt, tmp, nbchar)) {
2853                         if (ctxt->sax->ignorableWhitespace != NULL)
2854                             ctxt->sax->ignorableWhitespace(ctxt->userData,
2855                                                    tmp, nbchar);
2856                     } else {
2857                         if (ctxt->sax->characters != NULL)
2858                             ctxt->sax->characters(ctxt->userData,
2859                                                   tmp, nbchar);
2860                     }
2861                     line = ctxt->input->line;
2862                     col = ctxt->input->col;
2863                 } else {
2864                     if (ctxt->sax->characters != NULL)
2865                         ctxt->sax->characters(ctxt->userData,
2866                                               ctxt->input->cur, nbchar);
2867                     line = ctxt->input->line;
2868                     col = ctxt->input->col;
2869                 }
2870             }
2871             ctxt->input->cur = in;
2872             if (*in == 0xD) {
2873                 in++;
2874                 if (*in == 0xA) {
2875                     ctxt->input->cur = in;
2876                     in++;
2877                     ctxt->input->line++;
2878                     continue; /* while */
2879                 }
2880                 in--;
2881             }
2882             if (*in == '<') {
2883                 return;
2884             }
2885             if (*in == '&') {
2886                 return;
2887             }
2888             SHRINK;
2889             GROW;
2890             in = ctxt->input->cur;
2891         } while ((*in >= 0x20) && (*in <= 0x7F));
2892         nbchar = 0;
2893     }
2894     ctxt->input->line = line;
2895     ctxt->input->col = col;
2896     xmlParseCharDataComplex(ctxt, cdata);
2897 }
2898
2899 /**
2900  * xmlParseCharDataComplex:
2901  * @ctxt:  an XML parser context
2902  * @cdata:  int indicating whether we are within a CDATA section
2903  *
2904  * parse a CharData section.this is the fallback function
2905  * of xmlParseCharData() when the parsing requires handling
2906  * of non-ASCII characters.
2907  */
2908 void
2909 xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
2910     xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
2911     int nbchar = 0;
2912     int cur, l;
2913     int count = 0;
2914
2915     SHRINK;
2916     GROW;
2917     cur = CUR_CHAR(l);
2918     while ((cur != '<') && /* checked */
2919            (cur != '&') && 
2920            (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
2921         if ((cur == ']') && (NXT(1) == ']') &&
2922             (NXT(2) == '>')) {
2923             if (cdata) break;
2924             else {
2925                 ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
2926                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2927                     ctxt->sax->error(ctxt->userData,
2928                        "Sequence ']]>' not allowed in content\n");
2929                 /* Should this be relaxed ??? I see a "must here */
2930                 ctxt->wellFormed = 0;
2931                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
2932             }
2933         }
2934         COPY_BUF(l,buf,nbchar,cur);
2935         if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
2936             /*
2937              * OK the segment is to be consumed as chars.
2938              */
2939             if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
2940                 if (areBlanks(ctxt, buf, nbchar)) {
2941                     if (ctxt->sax->ignorableWhitespace != NULL)
2942                         ctxt->sax->ignorableWhitespace(ctxt->userData,
2943                                                        buf, nbchar);
2944                 } else {
2945                     if (ctxt->sax->characters != NULL)
2946                         ctxt->sax->characters(ctxt->userData, buf, nbchar);
2947                 }
2948             }
2949             nbchar = 0;
2950         }
2951         count++;
2952         if (count > 50) {
2953             GROW;
2954             count = 0;
2955         }
2956         NEXTL(l);
2957         cur = CUR_CHAR(l);
2958     }
2959     if (nbchar != 0) {
2960         /*
2961          * OK the segment is to be consumed as chars.
2962          */
2963         if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
2964             if (areBlanks(ctxt, buf, nbchar)) {
2965                 if (ctxt->sax->ignorableWhitespace != NULL)
2966                     ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2967             } else {
2968                 if (ctxt->sax->characters != NULL)
2969                     ctxt->sax->characters(ctxt->userData, buf, nbchar);
2970             }
2971         }
2972     }
2973 }
2974
2975 /**
2976  * xmlParseExternalID:
2977  * @ctxt:  an XML parser context
2978  * @publicID:  a xmlChar** receiving PubidLiteral
2979  * @strict: indicate whether we should restrict parsing to only
2980  *          production [75], see NOTE below
2981  *
2982  * Parse an External ID or a Public ID
2983  *
2984  * NOTE: Productions [75] and [83] interact badly since [75] can generate
2985  *       'PUBLIC' S PubidLiteral S SystemLiteral
2986  *
2987  * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2988  *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
2989  *
2990  * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2991  *
2992  * Returns the function returns SystemLiteral and in the second
2993  *                case publicID receives PubidLiteral, is strict is off
2994  *                it is possible to return NULL and have publicID set.
2995  */
2996
2997 xmlChar *
2998 xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2999     xmlChar *URI = NULL;
3000
3001     SHRINK;
3002
3003     *publicID = NULL;
3004     if ((RAW == 'S') && (NXT(1) == 'Y') &&
3005          (NXT(2) == 'S') && (NXT(3) == 'T') &&
3006          (NXT(4) == 'E') && (NXT(5) == 'M')) {
3007         SKIP(6);
3008         if (!IS_BLANK(CUR)) {
3009             ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3010             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3011                 ctxt->sax->error(ctxt->userData,
3012                     "Space required after 'SYSTEM'\n");
3013             ctxt->wellFormed = 0;
3014             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3015         }
3016         SKIP_BLANKS;
3017         URI = xmlParseSystemLiteral(ctxt);
3018         if (URI == NULL) {
3019             ctxt->errNo = XML_ERR_URI_REQUIRED;
3020             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3021                 ctxt->sax->error(ctxt->userData,
3022                   "xmlParseExternalID: SYSTEM, no URI\n");
3023             ctxt->wellFormed = 0;
3024             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3025         }
3026     } else if ((RAW == 'P') && (NXT(1) == 'U') &&
3027                (NXT(2) == 'B') && (NXT(3) == 'L') &&
3028                (NXT(4) == 'I') && (NXT(5) == 'C')) {
3029         SKIP(6);
3030         if (!IS_BLANK(CUR)) {
3031             ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3032             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3033                 ctxt->sax->error(ctxt->userData,
3034                     "Space required after 'PUBLIC'\n");
3035             ctxt->wellFormed = 0;
3036             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3037         }
3038         SKIP_BLANKS;
3039         *publicID = xmlParsePubidLiteral(ctxt);
3040         if (*publicID == NULL) {
3041             ctxt->errNo = XML_ERR_PUBID_REQUIRED;
3042             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3043                 ctxt->sax->error(ctxt->userData, 
3044                   "xmlParseExternalID: PUBLIC, no Public Identifier\n");
3045             ctxt->wellFormed = 0;
3046             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3047         }
3048         if (strict) {
3049             /*
3050              * We don't handle [83] so "S SystemLiteral" is required.
3051              */
3052             if (!IS_BLANK(CUR)) {
3053                 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3054                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3055                     ctxt->sax->error(ctxt->userData,
3056                         "Space required after the Public Identifier\n");
3057                 ctxt->wellFormed = 0;
3058                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3059             }
3060         } else {
3061             /*
3062              * We handle [83] so we return immediately, if 
3063              * "S SystemLiteral" is not detected. From a purely parsing
3064              * point of view that's a nice mess.
3065              */
3066             const xmlChar *ptr;
3067             GROW;
3068
3069             ptr = CUR_PTR;
3070             if (!IS_BLANK(*ptr)) return(NULL);
3071             
3072             while (IS_BLANK(*ptr)) ptr++; /* TODO: dangerous, fix ! */
3073             if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
3074         }
3075         SKIP_BLANKS;
3076         URI = xmlParseSystemLiteral(ctxt);
3077         if (URI == NULL) {
3078             ctxt->errNo = XML_ERR_URI_REQUIRED;
3079             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3080                 ctxt->sax->error(ctxt->userData, 
3081                    "xmlParseExternalID: PUBLIC, no URI\n");
3082             ctxt->wellFormed = 0;
3083             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3084         }
3085     }
3086     return(URI);
3087 }
3088
3089 /**
3090  * xmlParseComment:
3091  * @ctxt:  an XML parser context
3092  *
3093  * Skip an XML (SGML) comment <!-- .... -->
3094  *  The spec says that "For compatibility, the string "--" (double-hyphen)
3095  *  must not occur within comments. "
3096  *
3097  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
3098  */
3099 void
3100 xmlParseComment(xmlParserCtxtPtr ctxt) {
3101     xmlChar *buf = NULL;
3102     int len;
3103     int size = XML_PARSER_BUFFER_SIZE;
3104     int q, ql;
3105     int r, rl;
3106     int cur, l;
3107     xmlParserInputState state;
3108     xmlParserInputPtr input = ctxt->input;
3109     int count = 0;
3110
3111     /*
3112      * Check that there is a comment right here.
3113      */
3114     if ((RAW != '<') || (NXT(1) != '!') ||
3115         (NXT(2) != '-') || (NXT(3) != '-')) return;
3116
3117     state = ctxt->instate;
3118     ctxt->instate = XML_PARSER_COMMENT;
3119     SHRINK;
3120     SKIP(4);
3121     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3122     if (buf == NULL) {
3123         xmlGenericError(xmlGenericErrorContext,
3124                 "malloc of %d byte failed\n", size);
3125         ctxt->instate = state;
3126         return;
3127     }
3128     q = CUR_CHAR(ql);
3129     NEXTL(ql);
3130     r = CUR_CHAR(rl);
3131     NEXTL(rl);
3132     cur = CUR_CHAR(l);
3133     len = 0;
3134     while (IS_CHAR(cur) && /* checked */
3135            ((cur != '>') ||
3136             (r != '-') || (q != '-'))) {
3137         if ((r == '-') && (q == '-')) {
3138             ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
3139             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3140                 ctxt->sax->error(ctxt->userData,
3141                "Comment must not contain '--' (double-hyphen)`\n");
3142             ctxt->wellFormed = 0;
3143             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3144         }
3145         if (len + 5 >= size) {
3146             size *= 2;
3147             buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
3148             if (buf == NULL) {
3149                 xmlGenericError(xmlGenericErrorContext,
3150                         "realloc of %d byte failed\n", size);
3151                 ctxt->instate = state;
3152                 return;
3153             }
3154         }
3155         COPY_BUF(ql,buf,len,q);
3156         q = r;
3157         ql = rl;
3158         r = cur;
3159         rl = l;
3160
3161         count++;
3162         if (count > 50) {
3163             GROW;
3164             count = 0;
3165         }
3166         NEXTL(l);
3167         cur = CUR_CHAR(l);
3168         if (cur == 0) {
3169             SHRINK;
3170             GROW;
3171             cur = CUR_CHAR(l);
3172         }
3173     }
3174     buf[len] = 0;
3175     if (!IS_CHAR(cur)) {
3176         ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
3177         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3178             ctxt->sax->error(ctxt->userData,
3179                              "Comment not terminated \n<!--%.50s\n", buf);
3180         ctxt->wellFormed = 0;
3181         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3182         xmlFree(buf);
3183     } else {
3184         if (input != ctxt->input) {
3185             ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
3186             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3187                 ctxt->sax->error(ctxt->userData, 
3188 "Comment doesn't start and stop in the same entity\n");
3189             ctxt->wellFormed = 0;
3190             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3191         }
3192         NEXT;
3193         if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
3194             (!ctxt->disableSAX))
3195             ctxt->sax->comment(ctxt->userData, buf);
3196         xmlFree(buf);
3197     }
3198     ctxt->instate = state;
3199 }
3200
3201 /**
3202  * xmlParsePITarget:
3203  * @ctxt:  an XML parser context
3204  * 
3205  * parse the name of a PI
3206  *
3207  * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
3208  *
3209  * Returns the PITarget name or NULL
3210  */
3211
3212 xmlChar *
3213 xmlParsePITarget(xmlParserCtxtPtr ctxt) {
3214     xmlChar *name;
3215
3216     name = xmlParseName(ctxt);
3217     if ((name != NULL) &&
3218         ((name[0] == 'x') || (name[0] == 'X')) &&
3219         ((name[1] == 'm') || (name[1] == 'M')) &&
3220         ((name[2] == 'l') || (name[2] == 'L'))) {
3221         int i;
3222         if ((name[0] == 'x') && (name[1] == 'm') &&
3223             (name[2] == 'l') && (name[3] == 0)) {
3224             ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
3225             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3226                 ctxt->sax->error(ctxt->userData,
3227                  "XML declaration allowed only at the start of the document\n");
3228             ctxt->wellFormed = 0;
3229             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3230             return(name);
3231         } else if (name[3] == 0) {
3232             ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
3233             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3234                 ctxt->sax->error(ctxt->userData, "Invalid PI name\n");
3235             ctxt->wellFormed = 0;
3236             if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3237             return(name);
3238         }
3239         for (i = 0;;i++) {
3240             if (xmlW3CPIs[i] == NULL) break;
3241             if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
3242                 return(name);
3243         }
3244         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
3245             ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
3246             ctxt->sax->warning(ctxt->userData,
3247                  "xmlParsePITarget: invalid name prefix 'xml'\n");
3248         }
3249     }
3250     return(name);
3251 }
3252
3253 #ifdef LIBXML_CATALOG_ENABLED
3254 /**
3255  * xmlParseCatalogPI:
3256  * @ctxt:  an XML parser context
3257  * @catalog:  the PI value string
3258  * 
3259  * parse an XML Catalog Processing Instruction.
3260  *
3261  * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
3262  *
3263  * Occurs only if allowed by the user and if happening in the Misc
3264  * part of the document before any doctype informations
3265  * This will add the given catalog to the parsing context in order
3266  * to be used if there is a resolution need further down in the document
3267  */
3268
3269 static void
3270 xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
3271     xmlChar *URL = NULL;
3272     const xmlChar *tmp, *base;
3273     xmlChar marker;
3274
3275     tmp = catalog;
3276     while (IS_BLANK(*tmp)) tmp++;
3277     if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
3278         goto error;
3279     tmp += 7;
3280     while (IS_BLANK(*tmp)) tmp++;
3281     if (*tmp != '=') {
3282         return;
3283     }
3284     tmp++;
3285     while (IS_BLANK(*tmp)) tmp++;
3286     marker = *tmp;
3287     if ((marker != '\'') && (marker != '"'))
3288         goto error;
3289     tmp++;
3290     base = tmp;
3291     while ((*tmp != 0) && (*tmp != marker)) tmp++;
3292     if (*tmp == 0)
3293         goto error;
3294     URL = xmlStrndup(base, tmp - base);
3295     tmp++;
3296     while (IS_BLANK(*tmp)) tmp++;
3297     if (*tmp != 0)
3298         goto error;
3299
3300     if (URL != NULL) {
3301         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
3302         xmlFree(URL);
3303     }
3304     return;
3305
3306 error:
3307     ctxt->errNo = XML_WAR_CATALOG_PI;
3308     if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
3309         ctxt->sax->warning(ctxt->userData, 
3310              "Catalog PI syntax error: %s\n", catalog);
3311     if (URL != NULL)
3312         xmlFree(URL);
3313 }
3314 #endif
3315
3316 /**
3317  * xmlParsePI:
3318  * @ctxt:  an XML parser context
3319  * 
3320  * parse an XML Processing Instruction.
3321  *
3322  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
3323  *
3324  * The processing is transfered to SAX once parsed.
3325  */
3326
3327 void
3328 xmlParsePI(xmlParserCtxtPtr ctxt) {
3329     xmlChar *buf = NULL;
3330     int len = 0;
3331     int size = XML_PARSER_BUFFER_SIZE;
3332     int cur, l;
3333     xmlChar *target;
3334     xmlParserInputState state;
3335     int count = 0;
3336
3337     if ((RAW == '<') && (NXT(1) == '?')) {
3338         xmlParserInputPtr input = ctxt->input;
3339         state = ctxt->instate;
3340         ctxt->instate = XML_PARSER_PI;
3341         /*
3342          * this is a Processing Instruction.
3343          */
3344         SKIP(2);
3345         SHRINK;
3346
3347         /*
3348          * Parse the target name and check for special support like
3349          * namespace.
3350          */
3351         target = xmlParsePITarget(ctxt);
3352         if (target != NULL) {
3353             if ((RAW == '?') && (NXT(1) == '>')) {
3354                 if (input != ctxt->input) {
3355                     ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
3356                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3357                         ctxt->sax->error(ctxt->userData, 
3358     "PI declaration doesn't start and stop in the same entity\n");
3359                     ctxt->wellFormed = 0;
3360                     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3361                 }
3362                 SKIP(2);
3363
3364                 /*
3365                  * SAX: PI detected.
3366                  */
3367                 if ((ctxt->sax) && (!ctxt->disableSAX) &&
3368                     (ctxt->sax->processingInstruction != NULL))
3369                     ctxt->sax->processingInstruction(ctxt->userData,
3370                                                      target, NULL);
3371                 ctxt->instate = state;
3372                 xmlFree(target);
3373                 return;
3374             }
3375             buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3376             if (buf == NULL) {
3377                 xmlGenericError(xmlGenericErrorContext,
3378                         "malloc of %d byte failed\n", size);
3379                 ctxt->instate = state;
3380                 return;
3381             }
3382             cur = CUR;
3383             if (!IS_BLANK(cur)) {
3384                 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3385                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3386                     ctxt->sax->error(ctxt->userData,
3387                       "xmlParsePI: PI %s space expected\n", target);
3388                 ctxt->wellFormed = 0;
3389                 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
3390             }
3391             SKIP_BLANKS;
3392             cur = CUR_CHAR(l);
3393             while (IS_CHAR(cur) && /* checked */