source: trunk/third/libxml/parserold.c @ 16738

Revision 16738, 197.2 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16737, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * parserold.c : the 1.8.11 XML parser core added for compatibility
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel.Veillard@w3.org
7 */
8
9#ifdef WIN32
10#include "win32config.h"
11#else
12#include "config.h"
13#endif
14
15#include <stdio.h>
16#include <string.h> /* for memset() only */
17#ifdef HAVE_CTYPE_H
18#include <ctype.h>
19#endif
20#ifdef HAVE_STDLIB_H
21#include <stdlib.h>
22#endif
23#ifdef HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#ifdef HAVE_FCNTL_H
27#include <fcntl.h>
28#endif
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32#ifdef HAVE_ZLIB_H
33#include <zlib.h>
34#endif
35
36#include "xmlmemory.h"
37#include "tree.h"
38#include "parser.h"
39#include "entities.h"
40#include "encoding.h"
41#include "valid.h"
42#include "parserInternals.h"
43#include "xmlIO.h"
44#include "xml-error.h"
45
46#define XML_PARSER_BIG_BUFFER_SIZE 1000
47#define XML_PARSER_BUFFER_SIZE 100
48
49/*
50 * List of XML prefixed PI allowed by W3C specs
51 */
52
53static const char *xmlW3CPIs[] = {
54    "xml-stylesheet",
55    NULL
56};
57
58/************************************************************************
59 *                                                                      *
60 *              Tweaks for plugging in the old parser                   *
61 *                                                                      *
62 ************************************************************************/
63
64static void xmlOldFreeInputStream(xmlParserInputPtr input);
65static xmlChar * xmlOldParseName(xmlParserCtxtPtr ctxt);
66static xmlEntityPtr xmlOldParseEntityRef(xmlParserCtxtPtr ctxt);
67static void xmlOldParsePEReference(xmlParserCtxtPtr ctxt);
68static void xmlOldParseReference(xmlParserCtxtPtr ctxt);
69static xmlChar * xmlOldParseVersionInfo(xmlParserCtxtPtr ctxt);
70static xmlChar * xmlOldParseEncodingDecl(xmlParserCtxtPtr ctxt);
71static void xmlOldParseElement(xmlParserCtxtPtr ctxt);
72static xmlChar * xmlOldScanName(xmlParserCtxtPtr ctxt);
73static xmlEntityPtr
74xmlOldParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str);
75static xmlEntityPtr
76xmlOldParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str);
77
78extern xmlChar * xmlCharStrdup(const char *cur);
79
80/************************************************************************
81 *                                                                      *
82 *              Input handling functions for progressive parsing        *
83 *                                                                      *
84 ************************************************************************/
85
86/* #define DEBUG_INPUT */
87/* #define DEBUG_STACK */
88/* #define DEBUG_PUSH */
89
90
91#define INPUT_CHUNK     250
92/* we need to keep enough input to show errors in context */
93#define LINE_LEN        80
94
95#ifdef DEBUG_INPUT
96#define CHECK_BUFFER(in) check_buffer(in)
97
98static void old_check_buffer(xmlParserInputPtr in) {
99    if (in->base != in->buf->buffer->content) {
100        fprintf(stderr, "xmlParserInput: base mismatch problem\n");
101    }
102    if (in->cur < in->base) {
103        fprintf(stderr, "xmlParserInput: cur < base problem\n");
104    }
105    if (in->cur > in->base + in->buf->buffer->use) {
106        fprintf(stderr, "xmlParserInput: cur > base + use problem\n");
107    }
108    fprintf(stderr,"buffer %x : content %x, cur %d, use %d, size %d\n",
109            (int) in, (int) in->buf->buffer->content, in->cur - in->base,
110            in->buf->buffer->use, in->buf->buffer->size);
111}
112
113#else
114#define CHECK_BUFFER(in)
115#endif
116
117
118/**
119 * xmlOldParserInputRead:
120 * @in:  an XML parser input
121 * @len:  an indicative size for the lookahead
122 *
123 * This function refresh the input for the parser. It doesn't try to
124 * preserve pointers to the input buffer, and discard already read data
125 *
126 * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
127 * end of this entity
128 */
129static int
130xmlOldParserInputRead(xmlParserInputPtr in, int len) {
131    int ret;
132    int used;
133    int index;
134
135#ifdef DEBUG_INPUT
136    fprintf(stderr, "Read\n");
137#endif
138    if (in->buf == NULL) return(-1);
139    if (in->base == NULL) return(-1);
140    if (in->cur == NULL) return(-1);
141    if (in->buf->buffer == NULL) return(-1);
142
143    CHECK_BUFFER(in);
144
145    used = in->cur - in->buf->buffer->content;
146    ret = xmlBufferShrink(in->buf->buffer, used);
147    if (ret > 0) {
148        in->cur -= ret;
149        in->consumed += ret;
150    }
151    ret = xmlParserInputBufferRead(in->buf, len);
152    if (in->base != in->buf->buffer->content) {
153        /*
154         * the buffer has been realloced
155         */
156        index = in->cur - in->base;
157        in->base = in->buf->buffer->content;
158        in->cur = &in->buf->buffer->content[index];
159    }
160
161    CHECK_BUFFER(in);
162
163    return(ret);
164}
165
166/**
167 * xmlOldParserInputGrow:
168 * @in:  an XML parser input
169 * @len:  an indicative size for the lookahead
170 *
171 * This function increase the input for the parser. It tries to
172 * preserve pointers to the input buffer, and keep already read data
173 *
174 * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
175 * end of this entity
176 */
177static int
178xmlOldParserInputGrow(xmlParserInputPtr in, int len) {
179    int ret;
180    int index;
181
182#ifdef DEBUG_INPUT
183    fprintf(stderr, "Grow\n");
184#endif
185    if (in->buf == NULL) return(-1);
186    if (in->base == NULL) return(-1);
187    if (in->cur == NULL) return(-1);
188    if (in->buf->buffer == NULL) return(-1);
189
190    CHECK_BUFFER(in);
191
192    index = in->cur - in->base;
193    if (in->buf->buffer->use > index + INPUT_CHUNK) {
194
195        CHECK_BUFFER(in);
196
197        return(0);
198    }
199    if ((in->buf->httpIO != NULL) || (in->buf->ftpIO != NULL) ||
200        (in->buf->file != NULL) ||
201#ifdef HAVE_ZLIB_H
202        (in->buf->gzfile != NULL) ||
203#endif
204        (in->buf->fd >= 0))
205        ret = xmlParserInputBufferGrow(in->buf, len);
206    else       
207        return(0);
208
209    /*
210     * NOTE : in->base may be a "dandling" i.e. freed pointer in this
211     *        block, but we use it really as an integer to do some
212     *        pointer arithmetic. Insure will raise it as a bug but in
213     *        that specific case, that's not !
214     */
215    if (in->base != in->buf->buffer->content) {
216        /*
217         * the buffer has been realloced
218         */
219        index = in->cur - in->base;
220        in->base = in->buf->buffer->content;
221        in->cur = &in->buf->buffer->content[index];
222    }
223
224    CHECK_BUFFER(in);
225
226    return(ret);
227}
228
229/**
230 * xmlOldParserInputShrink:
231 * @in:  an XML parser input
232 *
233 * This function removes used input for the parser.
234 */
235static void
236xmlOldParserInputShrink(xmlParserInputPtr in) {
237    int used;
238    int ret;
239    int index;
240
241#ifdef DEBUG_INPUT
242    fprintf(stderr, "Shrink\n");
243#endif
244    if (in->buf == NULL) return;
245    if (in->base == NULL) return;
246    if (in->cur == NULL) return;
247    if (in->buf->buffer == NULL) return;
248
249    CHECK_BUFFER(in);
250
251    used = in->cur - in->buf->buffer->content;
252    if (used > INPUT_CHUNK) {
253        ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
254        if (ret > 0) {
255            in->cur -= ret;
256            in->consumed += ret;
257        }
258    }
259
260    CHECK_BUFFER(in);
261
262    if (in->buf->buffer->use > INPUT_CHUNK) {
263        return;
264    }
265    xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
266    if (in->base != in->buf->buffer->content) {
267        /*
268         * the buffer has been realloced
269         */
270        index = in->cur - in->base;
271        in->base = in->buf->buffer->content;
272        in->cur = &in->buf->buffer->content[index];
273    }
274
275    CHECK_BUFFER(in);
276}
277
278/************************************************************************
279 *                                                                      *
280 *              Parser stacks related functions and macros              *
281 *                                                                      *
282 ************************************************************************/
283
284extern int xmlSubstituteEntitiesDefaultValue;
285extern int xmlDoValidityCheckingDefaultValue;
286extern int xmlKeepBlanksDefaultValue;
287xmlEntityPtr xmlOldParseStringEntityRef(xmlParserCtxtPtr ctxt,
288                                     const xmlChar ** str);
289
290/*
291 * Generic function for accessing stacks in the Parser Context
292 */
293
294#define PUSH_AND_POP(scope, type, name)                                 \
295scope int name##OldPush(xmlParserCtxtPtr ctxt, type value) {            \
296    if (ctxt->name##Nr >= ctxt->name##Max) {                            \
297        ctxt->name##Max *= 2;                                           \
298        ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab,          \
299                     ctxt->name##Max * sizeof(ctxt->name##Tab[0]));     \
300        if (ctxt->name##Tab == NULL) {                                  \
301            fprintf(stderr, "realloc failed !\n");                      \
302            return(0);                                                  \
303        }                                                               \
304    }                                                                   \
305    ctxt->name##Tab[ctxt->name##Nr] = value;                            \
306    ctxt->name = value;                                                 \
307    return(ctxt->name##Nr++);                                           \
308}                                                                       \
309scope type name##OldPop(xmlParserCtxtPtr ctxt) {                        \
310    type ret;                                                           \
311    if (ctxt->name##Nr <= 0) return(0);                                 \
312    ctxt->name##Nr--;                                                   \
313    if (ctxt->name##Nr > 0)                                             \
314        ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];               \
315    else                                                                \
316        ctxt->name = NULL;                                              \
317    ret = ctxt->name##Tab[ctxt->name##Nr];                              \
318    ctxt->name##Tab[ctxt->name##Nr] = 0;                                \
319    return(ret);                                                        \
320}                                                                       \
321
322PUSH_AND_POP(static, xmlParserInputPtr, input)
323PUSH_AND_POP(static, xmlNodePtr, node)
324PUSH_AND_POP(static, xmlChar*, name)
325
326/*
327 * Macros for accessing the content. Those should be used only by the parser,
328 * and not exported.
329 *
330 * Dirty macros, i.e. one need to make assumption on the context to use them
331 *
332 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
333 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
334 *           in ISO-Latin or UTF-8, and the current 16 bit value if compiled
335 *           in UNICODE mode. This should be used internally by the parser
336 *           only to compare to ASCII values otherwise it would break when
337 *           running with UTF-8 encoding.
338 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
339 *           to compare on ASCII based substring.
340 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
341 *           strings within the parser.
342 *
343 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
344 *
345 *   CURRENT Returns the current char value, with the full decoding of
346 *           UTF-8 if we are using this mode. It returns an int.
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 *   COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
350 */
351
352#define RAW (ctxt->token ? -1 : (*ctxt->input->cur))
353#define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
354#define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val)
355#define NXT(val) ctxt->input->cur[(val)]
356#define CUR_PTR ctxt->input->cur
357#define SHRINK  xmlOldParserInputShrink(ctxt->input);                   \
358    if ((*ctxt->input->cur == 0) &&                                     \
359        (xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))         \
360            xmlOldPopInput(ctxt)
361
362#define GROW  xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK);          \
363    if ((*ctxt->input->cur == 0) &&                                     \
364        (xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))         \
365            xmlOldPopInput(ctxt)
366
367#define SKIP_BLANKS                                                     \
368    do {                                                                \
369        while (IS_BLANK(CUR)) NEXT;                                     \
370        while ((CUR == 0) && (ctxt->inputNr > 1))                       \
371            xmlOldPopInput(ctxt);                                               \
372        if (*ctxt->input->cur == '%') xmlOldParserHandlePEReference(ctxt);      \
373        if (*ctxt->input->cur == '&') xmlOldParserHandleReference(ctxt);        \
374    } while (IS_BLANK(CUR));
375
376#define CURRENT (*ctxt->input->cur)
377#define NEXT {                                                          \
378    if (ctxt->token != 0) ctxt->token = 0;                              \
379    else {                                                              \
380    if ((*ctxt->input->cur == 0) &&                                     \
381        (xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {               \
382            xmlOldPopInput(ctxt);                                               \
383    } else {                                                            \
384        if (*(ctxt->input->cur) == '\n') {                              \
385            ctxt->input->line++; ctxt->input->col = 1;                  \
386        } else ctxt->input->col++;                                      \
387        ctxt->input->cur++;                                             \
388        ctxt->nbChars++;                                                \
389        if (*ctxt->input->cur == 0)                                     \
390            xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK);            \
391    }                                                                   \
392    if (*ctxt->input->cur == '%') xmlOldParserHandlePEReference(ctxt);  \
393    if (*ctxt->input->cur == '&') xmlOldParserHandleReference(ctxt);    \
394}}
395
396
397/************************************************************************
398 *                                                                      *
399 *      Commodity functions to handle entities processing               *
400 *                                                                      *
401 ************************************************************************/
402
403/**
404 * xmlOldPopInput:
405 * @ctxt:  an XML parser context
406 *
407 * xmlOldPopInput: the current input pointed by ctxt->input came to an end
408 *          pop it and return the next char.
409 *
410 * Returns the current xmlChar in the parser context
411 */
412static xmlChar
413xmlOldPopInput(xmlParserCtxtPtr ctxt) {
414    if (ctxt->inputNr == 1) return(0); /* End of main Input */
415    xmlOldFreeInputStream(inputOldPop(ctxt));
416    if ((*ctxt->input->cur == 0) &&
417        (xmlOldParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
418            return(xmlOldPopInput(ctxt));
419    return(CUR);
420}
421
422/**
423 * xmlOldPushInput:
424 * @ctxt:  an XML parser context
425 * @input:  an XML parser input fragment (entity, XML fragment ...).
426 *
427 * xmlOldPushInput: switch to a new input stream which is stacked on top
428 *               of the previous one(s).
429 */
430void
431xmlOldPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
432    if (input == NULL) return;
433    inputOldPush(ctxt, input);
434}
435
436/**
437 * xmlOldFreeInputStream:
438 * @input:  an xmlParserInputPtr
439 *
440 * Free up an input stream.
441 */
442static void
443xmlOldFreeInputStream(xmlParserInputPtr input) {
444    if (input == NULL) return;
445
446    if (input->filename != NULL) xmlFree((char *) input->filename);
447    if (input->directory != NULL) xmlFree((char *) input->directory);
448    if ((input->free != NULL) && (input->base != NULL))
449        input->free((xmlChar *) input->base);
450    if (input->buf != NULL)
451        xmlFreeParserInputBuffer(input->buf);
452    memset(input, -1, sizeof(xmlParserInput));
453    xmlFree(input);
454}
455
456/**
457 * xmlOldNewInputStream:
458 * @ctxt:  an XML parser context
459 *
460 * Create a new input stream structure
461 * Returns the new input stream or NULL
462 */
463static xmlParserInputPtr
464xmlOldNewInputStream(xmlParserCtxtPtr ctxt) {
465    xmlParserInputPtr input;
466
467    input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
468    if (input == NULL) {
469        ctxt->errNo = XML_ERR_NO_MEMORY;
470        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
471            ctxt->sax->error(ctxt->userData,
472                             "malloc: couldn't allocate a new input stream\n");
473        ctxt->errNo = XML_ERR_NO_MEMORY;
474        return(NULL);
475    }
476    input->filename = NULL;
477    input->directory = NULL;
478    input->base = NULL;
479    input->cur = NULL;
480    input->buf = NULL;
481    input->line = 1;
482    input->col = 1;
483    input->buf = NULL;
484    input->free = NULL;
485    input->consumed = 0;
486    input->length = 0;
487    return(input);
488}
489
490/**
491 * xmlOldNewEntityInputStream:
492 * @ctxt:  an XML parser context
493 * @entity:  an Entity pointer
494 *
495 * Create a new input stream based on an xmlEntityPtr
496 *
497 * Returns the new input stream or NULL
498 */
499static xmlParserInputPtr
500xmlOldNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
501    xmlParserInputPtr input;
502
503    if (entity == NULL) {
504        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
505        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
506            ctxt->sax->error(ctxt->userData,
507              "internal: xmlOldNewEntityInputStream entity = NULL\n");
508        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
509        return(NULL);
510    }
511    if (entity->content == NULL) {
512        switch (entity->type) {
513            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
514                ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
515                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
516                    ctxt->sax->error(ctxt->userData,
517                      "xmlNewEntityInputStream unparsed entity !\n");
518                break;
519            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
520            case XML_EXTERNAL_PARAMETER_ENTITY:
521                return(xmlLoadExternalEntity((char *) entity->SystemID,
522                       (char *) entity->ExternalID, ctxt));
523            case XML_INTERNAL_GENERAL_ENTITY:
524                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
525                    ctxt->sax->error(ctxt->userData,
526          "Internal entity %s without content !\n", entity->name);
527                break;
528            case XML_INTERNAL_PARAMETER_ENTITY:
529                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
530                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
531                    ctxt->sax->error(ctxt->userData,
532          "Internal parameter entity %s without content !\n", entity->name);
533                break;
534            case XML_INTERNAL_PREDEFINED_ENTITY:
535                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
536                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
537                    ctxt->sax->error(ctxt->userData,
538              "Predefined entity %s without content !\n", entity->name);
539                break;
540        }
541        return(NULL);
542    }
543    input = xmlOldNewInputStream(ctxt);
544    if (input == NULL) {
545        return(NULL);
546    }
547    input->filename = (char *) entity->SystemID; /* TODO !!! char <- xmlChar */
548    input->base = entity->content;
549    input->cur = entity->content;
550    input->length = entity->length;
551    return(input);
552}
553
554/**
555 * xmlOldNewStringInputStream:
556 * @ctxt:  an XML parser context
557 * @buffer:  an memory buffer
558 *
559 * Create a new input stream based on a memory buffer.
560 * Returns the new input stream
561 */
562static xmlParserInputPtr
563xmlOldNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
564    xmlParserInputPtr input;
565
566    if (buffer == NULL) {
567        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
568        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
569            ctxt->sax->error(ctxt->userData,
570              "internal: xmlOldNewStringInputStream string = NULL\n");
571        return(NULL);
572    }
573    input = xmlOldNewInputStream(ctxt);
574    if (input == NULL) {
575        return(NULL);
576    }
577    input->base = buffer;
578    input->cur = buffer;
579    input->length = xmlStrlen(buffer);
580    return(input);
581}
582
583/**
584 * xmlOldNewInputFromFile:
585 * @ctxt:  an XML parser context
586 * @filename:  the filename to use as entity
587 *
588 * Create a new input stream based on a file.
589 *
590 * Returns the new input stream or NULL in case of error
591 */
592static xmlParserInputPtr
593xmlOldNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
594    xmlParserInputBufferPtr buf;
595    xmlParserInputPtr inputStream;
596    char *directory = NULL;
597
598    if (ctxt == NULL) return(NULL);
599    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
600    if (buf == NULL) {
601        char name[XML_PARSER_BIG_BUFFER_SIZE];
602
603        if ((ctxt->input != NULL) && (ctxt->input->directory != NULL)) {
604#ifdef WIN32
605            sprintf(name, "%s\\%s", ctxt->input->directory, filename);
606#else
607            sprintf(name, "%s/%s", ctxt->input->directory, filename);
608#endif
609            buf = xmlParserInputBufferCreateFilename(name,
610                                                     XML_CHAR_ENCODING_NONE);
611            if (buf != NULL)
612                directory = xmlParserGetDirectory(name);
613        }
614        if ((buf == NULL) && (ctxt->directory != NULL)) {
615#ifdef WIN32
616            sprintf(name, "%s\\%s", ctxt->directory, filename);
617#else
618            sprintf(name, "%s/%s", ctxt->directory, filename);
619#endif
620            buf = xmlParserInputBufferCreateFilename(name,
621                                                     XML_CHAR_ENCODING_NONE);
622            if (buf != NULL)
623                directory = xmlParserGetDirectory(name);
624        }
625        if (buf == NULL)
626            return(NULL);
627    }
628    if (directory == NULL)
629        directory = xmlParserGetDirectory(filename);
630
631    inputStream = xmlOldNewInputStream(ctxt);
632    if (inputStream == NULL) {
633        if (directory != NULL) xmlFree((char *) directory);
634        return(NULL);
635    }
636
637    inputStream->filename = xmlMemStrdup(filename);
638    inputStream->directory = directory;
639    inputStream->buf = buf;
640
641    inputStream->base = inputStream->buf->buffer->content;
642    inputStream->cur = inputStream->buf->buffer->content;
643    if ((ctxt->directory == NULL) && (directory != NULL))
644        ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory);
645    return(inputStream);
646}
647
648/************************************************************************
649 *                                                                      *
650 *              Commodity functions to handle entities                  *
651 *                                                                      *
652 ************************************************************************/
653
654static void xmlOldParserHandleReference(xmlParserCtxtPtr ctxt);
655static void xmlOldParserHandlePEReference(xmlParserCtxtPtr ctxt);
656xmlEntityPtr xmlOldParseStringPEReference(xmlParserCtxtPtr ctxt,
657                                       const xmlChar **str);
658
659/**
660 * xmlOldParseCharRef:
661 * @ctxt:  an XML parser context
662 *
663 * parse Reference declarations
664 *
665 * [66] CharRef ::= '&#' [0-9]+ ';' |
666 *                  '&#x' [0-9a-fA-F]+ ';'
667 *
668 * [ WFC: Legal Character ]
669 * Characters referred to using character references must match the
670 * production for Char.
671 *
672 * Returns the value parsed (as an int), 0 in case of error
673 */
674static int
675xmlOldParseCharRef(xmlParserCtxtPtr ctxt) {
676    int val = 0;
677
678    if (ctxt->token != 0) {
679        val = ctxt->token;
680        ctxt->token = 0;
681        return(val);
682    }
683    if ((CUR == '&') && (NXT(1) == '#') &&
684        (NXT(2) == 'x')) {
685        SKIP(3);
686        while (CUR != ';') {
687            if ((CUR >= '0') && (CUR <= '9'))
688                val = val * 16 + (CUR - '0');
689            else if ((CUR >= 'a') && (CUR <= 'f'))
690                val = val * 16 + (CUR - 'a') + 10;
691            else if ((CUR >= 'A') && (CUR <= 'F'))
692                val = val * 16 + (CUR - 'A') + 10;
693            else {
694                ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
695                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
696                    ctxt->sax->error(ctxt->userData,
697                         "xmlParseCharRef: invalid hexadecimal value\n");
698                ctxt->wellFormed = 0;
699                val = 0;
700                break;
701            }
702            NEXT;
703        }
704        if (CUR == ';')
705            SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
706    } else if  ((CUR == '&') && (NXT(1) == '#')) {
707        SKIP(2);
708        while (CUR != ';') {
709            if ((CUR >= '0') && (CUR <= '9'))
710                val = val * 10 + (CUR - '0');
711            else {
712                ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
713                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
714                    ctxt->sax->error(ctxt->userData,
715                         "xmlParseCharRef: invalid decimal value\n");
716                ctxt->wellFormed = 0;
717                val = 0;
718                break;
719            }
720            NEXT;
721        }
722        if (CUR == ';')
723            SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
724    } else {
725        ctxt->errNo = XML_ERR_INVALID_CHARREF;
726        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
727            ctxt->sax->error(ctxt->userData,
728               "xmlParseCharRef: invalid value\n");
729        ctxt->wellFormed = 0;
730    }
731
732    /*
733     * [ WFC: Legal Character ]
734     * Characters referred to using character references must match the
735     * production for Char.
736     */
737    if (IS_CHAR(val)) {
738        return(val);
739    } else {
740        ctxt->errNo = XML_ERR_INVALID_CHAR;
741        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
742            ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
743                             val);
744        ctxt->wellFormed = 0;
745    }
746    return(0);
747}
748
749/**
750 * xmlOldParseStringCharRef:
751 * @ctxt:  an XML parser context
752 * @str:  a pointer to an index in the string
753 *
754 * parse Reference declarations, variant parsing from a string rather
755 * than an an input flow.
756 *
757 * [66] CharRef ::= '&#' [0-9]+ ';' |
758 *                  '&#x' [0-9a-fA-F]+ ';'
759 *
760 * [ WFC: Legal Character ]
761 * Characters referred to using character references must match the
762 * production for Char.
763 *
764 * Returns the value parsed (as an int), 0 in case of error, str will be
765 *         updated to the current value of the index
766 */
767static int
768xmlOldParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
769    const xmlChar *ptr;
770    xmlChar cur;
771    int val = 0;
772
773    if ((str == NULL) || (*str == NULL)) return(0);
774    ptr = *str;
775    cur = *ptr;
776    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
777        ptr += 3;
778        cur = *ptr;
779        while (cur != ';') {
780            if ((cur >= '0') && (cur <= '9'))
781                val = val * 16 + (cur - '0');
782            else if ((cur >= 'a') && (cur <= 'f'))
783                val = val * 16 + (cur - 'a') + 10;
784            else if ((cur >= 'A') && (cur <= 'F'))
785                val = val * 16 + (cur - 'A') + 10;
786            else {
787                ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
788                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
789                    ctxt->sax->error(ctxt->userData,
790                         "xmlParseCharRef: invalid hexadecimal value\n");
791                ctxt->wellFormed = 0;
792                val = 0;
793                break;
794            }
795            ptr++;
796            cur = *ptr;
797        }
798        if (cur == ';')
799            ptr++;
800    } else if  ((cur == '&') && (ptr[1] == '#')){
801        ptr += 2;
802        cur = *ptr;
803        while (cur != ';') {
804            if ((cur >= '0') && (cur <= '9'))
805                val = val * 10 + (cur - '0');
806            else {
807                ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
808                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
809                    ctxt->sax->error(ctxt->userData,
810                         "xmlParseCharRef: invalid decimal value\n");
811                ctxt->wellFormed = 0;
812                val = 0;
813                break;
814            }
815            ptr++;
816            cur = *ptr;
817        }
818        if (cur == ';')
819            ptr++;
820    } else {
821        ctxt->errNo = XML_ERR_INVALID_CHARREF;
822        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
823            ctxt->sax->error(ctxt->userData,
824               "xmlParseCharRef: invalid value\n");
825        ctxt->wellFormed = 0;
826        return(0);
827    }
828    *str = ptr;
829
830    /*
831     * [ WFC: Legal Character ]
832     * Characters referred to using character references must match the
833     * production for Char.
834     */
835    if (IS_CHAR(val)) {
836        return(val);
837    } else {
838        ctxt->errNo = XML_ERR_INVALID_CHAR;
839        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
840            ctxt->sax->error(ctxt->userData,
841                             "CharRef: invalid xmlChar value %d\n", val);
842        ctxt->wellFormed = 0;
843    }
844    return(0);
845}
846
847/**
848 * xmlOldParserHandleReference:
849 * @ctxt:  the parser context
850 *
851 * [67] Reference ::= EntityRef | CharRef
852 *
853 * [68] EntityRef ::= '&' Name ';'
854 *
855 * [ WFC: Entity Declared ]
856 * the Name given in the entity reference must match that in an entity
857 * declaration, except that well-formed documents need not declare any
858 * of the following entities: amp, lt, gt, apos, quot.
859 *
860 * [ WFC: Parsed Entity ]
861 * An entity reference must not contain the name of an unparsed entity
862 *
863 * [66] CharRef ::= '&#' [0-9]+ ';' |
864 *                  '&#x' [0-9a-fA-F]+ ';'
865 *
866 * A PEReference may have been detectect in the current input stream
867 * the handling is done accordingly to
868 *      http://www.w3.org/TR/REC-xml#entproc
869 */
870static void
871xmlOldParserHandleReference(xmlParserCtxtPtr ctxt) {
872    xmlParserInputPtr input;
873    xmlChar *name;
874    xmlEntityPtr ent = NULL;
875
876    if (ctxt->token != 0) {
877        return;
878    }   
879    if (CUR != '&') return;
880    GROW;
881    if ((CUR == '&') && (NXT(1) == '#')) {
882        switch(ctxt->instate) {
883            case XML_PARSER_ENTITY_DECL:
884            case XML_PARSER_PI:
885            case XML_PARSER_CDATA_SECTION:
886            case XML_PARSER_COMMENT:
887                /* we just ignore it there */
888                return;
889            case XML_PARSER_START_TAG:
890                return;
891            case XML_PARSER_END_TAG:
892                return;
893            case XML_PARSER_EOF:
894                ctxt->errNo = XML_ERR_CHARREF_AT_EOF;
895                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
896                    ctxt->sax->error(ctxt->userData, "CharRef at EOF\n");
897                ctxt->wellFormed = 0;
898                return;
899            case XML_PARSER_PROLOG:
900            case XML_PARSER_START:
901            case XML_PARSER_MISC:
902                ctxt->errNo = XML_ERR_CHARREF_IN_PROLOG;
903                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
904                    ctxt->sax->error(ctxt->userData, "CharRef in prolog!\n");
905                ctxt->wellFormed = 0;
906                return;
907            case XML_PARSER_EPILOG:
908                ctxt->errNo = XML_ERR_CHARREF_IN_EPILOG;
909                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
910                    ctxt->sax->error(ctxt->userData, "CharRef in epilog!\n");
911                ctxt->wellFormed = 0;
912                return;
913            case XML_PARSER_DTD:
914                ctxt->errNo = XML_ERR_CHARREF_IN_DTD;
915                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
916                    ctxt->sax->error(ctxt->userData,
917                           "CharRef are forbiden in DTDs!\n");
918                ctxt->wellFormed = 0;
919                return;
920            case XML_PARSER_ENTITY_VALUE:
921                /*
922                 * NOTE: in the case of entity values, we don't do the
923                 *       substitution here since we need the literal
924                 *       entity value to be able to save the internal
925                 *       subset of the document.
926                 *       This will be handled by xmlOldDecodeEntities
927                 */
928                return;
929            case XML_PARSER_CONTENT:
930            case XML_PARSER_ATTRIBUTE_VALUE:
931                /* !!! this may not be Ok for UTF-8, multibyte sequence */
932                ctxt->token = xmlOldParseCharRef(ctxt);
933                return;
934        }
935        return;
936    }
937
938    switch(ctxt->instate) {
939        case XML_PARSER_CDATA_SECTION:
940            return;
941        case XML_PARSER_PI:
942        case XML_PARSER_COMMENT:
943            return;
944        case XML_PARSER_START_TAG:
945            return;
946        case XML_PARSER_END_TAG:
947            return;
948        case XML_PARSER_EOF:
949            ctxt->errNo = XML_ERR_ENTITYREF_AT_EOF;
950            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
951                ctxt->sax->error(ctxt->userData, "Reference at EOF\n");
952            ctxt->wellFormed = 0;
953            return;
954        case XML_PARSER_PROLOG:
955        case XML_PARSER_START:
956        case XML_PARSER_MISC:
957            ctxt->errNo = XML_ERR_ENTITYREF_IN_PROLOG;
958            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
959                ctxt->sax->error(ctxt->userData, "Reference in prolog!\n");
960            ctxt->wellFormed = 0;
961            return;
962        case XML_PARSER_EPILOG:
963            ctxt->errNo = XML_ERR_ENTITYREF_IN_EPILOG;
964            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
965                ctxt->sax->error(ctxt->userData, "Reference in epilog!\n");
966            ctxt->wellFormed = 0;
967            return;
968        case XML_PARSER_ENTITY_VALUE:
969            /*
970             * NOTE: in the case of entity values, we don't do the
971             *       substitution here since we need the literal
972             *       entity value to be able to save the internal
973             *       subset of the document.
974             *       This will be handled by xmlOldDecodeEntities
975             */
976            return;
977        case XML_PARSER_ATTRIBUTE_VALUE:
978            /*
979             * NOTE: in the case of attributes values, we don't do the
980             *       substitution here unless we are in a mode where
981             *       the parser is explicitely asked to substitute
982             *       entities. The SAX callback is called with values
983             *       without entity substitution.
984             *       This will then be handled by xmlOldDecodeEntities
985             */
986            return;
987        case XML_PARSER_ENTITY_DECL:
988            /*
989             * we just ignore it there
990             * the substitution will be done once the entity is referenced
991             */
992            return;
993        case XML_PARSER_DTD:
994            ctxt->errNo = XML_ERR_ENTITYREF_IN_DTD;
995            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
996                ctxt->sax->error(ctxt->userData,
997                       "Entity references are forbiden in DTDs!\n");
998            ctxt->wellFormed = 0;
999            return;
1000        case XML_PARSER_CONTENT:
1001            return;
1002    }
1003
1004    NEXT;
1005    name = xmlOldScanName(ctxt);
1006    if (name == NULL) {
1007        ctxt->errNo = XML_ERR_ENTITYREF_NO_NAME;
1008        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1009            ctxt->sax->error(ctxt->userData, "Entity reference: no name\n");
1010        ctxt->wellFormed = 0;
1011        ctxt->token = '&';
1012        return;
1013    }
1014    if (NXT(xmlStrlen(name)) != ';') {
1015        ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1016        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1017            ctxt->sax->error(ctxt->userData,
1018                             "Entity reference: ';' expected\n");
1019        ctxt->wellFormed = 0;
1020        ctxt->token = '&';
1021        xmlFree(name);
1022        return;
1023    }
1024    SKIP(xmlStrlen(name) + 1);
1025    if (ctxt->sax != NULL) {
1026        if (ctxt->sax->getEntity != NULL)
1027            ent = ctxt->sax->getEntity(ctxt->userData, name);
1028    }
1029
1030    /*
1031     * [ WFC: Entity Declared ]
1032     * the Name given in the entity reference must match that in an entity
1033     * declaration, except that well-formed documents need not declare any
1034     * of the following entities: amp, lt, gt, apos, quot.
1035     */
1036    if (ent == NULL)
1037        ent = xmlGetPredefinedEntity(name);
1038    if (ent == NULL) {
1039        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1040        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1041            ctxt->sax->error(ctxt->userData,
1042                             "Entity reference: entity %s not declared\n",
1043                             name);
1044        ctxt->wellFormed = 0;
1045        xmlFree(name);
1046        return;
1047    }
1048
1049    /*
1050     * [ WFC: Parsed Entity ]
1051     * An entity reference must not contain the name of an unparsed entity
1052     */
1053    if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1054        ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1055        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1056            ctxt->sax->error(ctxt->userData,
1057                         "Entity reference to unparsed entity %s\n", name);
1058        ctxt->wellFormed = 0;
1059    }
1060
1061    if (ent->type == XML_INTERNAL_PREDEFINED_ENTITY) {
1062        ctxt->token = ent->content[0];
1063        xmlFree(name);
1064        return;
1065    }
1066    input = xmlOldNewEntityInputStream(ctxt, ent);
1067    xmlOldPushInput(ctxt, input);
1068    xmlFree(name);
1069    return;
1070}
1071
1072/**
1073 * xmlOldParserHandlePEReference:
1074 * @ctxt:  the parser context
1075 *
1076 * [69] PEReference ::= '%' Name ';'
1077 *
1078 * [ WFC: No Recursion ]
1079 * TODO A parsed entity must not contain a recursive
1080 * reference to itself, either directly or indirectly.
1081 *
1082 * [ WFC: Entity Declared ]
1083 * In a document without any DTD, a document with only an internal DTD
1084 * subset which contains no parameter entity references, or a document
1085 * with "standalone='yes'", ...  ... The declaration of a parameter
1086 * entity must precede any reference to it...
1087 *
1088 * [ VC: Entity Declared ]
1089 * In a document with an external subset or external parameter entities
1090 * with "standalone='no'", ...  ... The declaration of a parameter entity
1091 * must precede any reference to it...
1092 *
1093 * [ WFC: In DTD ]
1094 * Parameter-entity references may only appear in the DTD.
1095 * NOTE: misleading but this is handled.
1096 *
1097 * A PEReference may have been detected in the current input stream
1098 * the handling is done accordingly to
1099 *      http://www.w3.org/TR/REC-xml#entproc
1100 * i.e.
1101 *   - Included in literal in entity values
1102 *   - Included as Paraemeter Entity reference within DTDs
1103 */
1104static void
1105xmlOldParserHandlePEReference(xmlParserCtxtPtr ctxt) {
1106    xmlChar *name;
1107    xmlEntityPtr entity = NULL;
1108    xmlParserInputPtr input;
1109
1110    if (ctxt->token != 0) {
1111        return;
1112    }   
1113    if (CUR != '%') return;
1114    switch(ctxt->instate) {
1115        case XML_PARSER_CDATA_SECTION:
1116            return;
1117        case XML_PARSER_COMMENT:
1118            return;
1119        case XML_PARSER_START_TAG:
1120            return;
1121        case XML_PARSER_END_TAG:
1122            return;
1123        case XML_PARSER_EOF:
1124            ctxt->errNo = XML_ERR_PEREF_AT_EOF;
1125            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1126                ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
1127            ctxt->wellFormed = 0;
1128            return;
1129        case XML_PARSER_PROLOG:
1130        case XML_PARSER_START:
1131        case XML_PARSER_MISC:
1132            ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
1133            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1134                ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
1135            ctxt->wellFormed = 0;
1136            return;
1137        case XML_PARSER_ENTITY_DECL:
1138        case XML_PARSER_CONTENT:
1139        case XML_PARSER_ATTRIBUTE_VALUE:
1140        case XML_PARSER_PI:
1141            /* we just ignore it there */
1142            return;
1143        case XML_PARSER_EPILOG:
1144            ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
1145            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1146                ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
1147            ctxt->wellFormed = 0;
1148            return;
1149        case XML_PARSER_ENTITY_VALUE:
1150            /*
1151             * NOTE: in the case of entity values, we don't do the
1152             *       substitution here since we need the literal
1153             *       entity value to be able to save the internal
1154             *       subset of the document.
1155             *       This will be handled by xmlOldDecodeEntities
1156             */
1157            return;
1158        case XML_PARSER_DTD:
1159            /*
1160             * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
1161             * In the internal DTD subset, parameter-entity references
1162             * can occur only where markup declarations can occur, not
1163             * within markup declarations.
1164             * In that case this is handled in xmlOldParseMarkupDecl
1165             */
1166            if ((ctxt->external == 0) && (ctxt->inputNr == 1))
1167                return;
1168    }
1169
1170    NEXT;
1171    name = xmlOldParseName(ctxt);
1172    if (name == NULL) {
1173        ctxt->errNo = XML_ERR_PEREF_NO_NAME;
1174        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1175            ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
1176        ctxt->wellFormed = 0;
1177    } else {
1178        if (CUR == ';') {
1179            NEXT;
1180            if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
1181                entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
1182            if (entity == NULL) {
1183               
1184                /*
1185                 * [ WFC: Entity Declared ]
1186                 * In a document without any DTD, a document with only an
1187                 * internal DTD subset which contains no parameter entity
1188                 * references, or a document with "standalone='yes'", ...
1189                 * ... The declaration of a parameter entity must precede
1190                 * any reference to it...
1191                 */
1192                if ((ctxt->standalone == 1) ||
1193                    ((ctxt->hasExternalSubset == 0) &&
1194                     (ctxt->hasPErefs == 0))) {
1195                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1196                        ctxt->sax->error(ctxt->userData,
1197                         "PEReference: %%%s; not found\n", name);
1198                    ctxt->wellFormed = 0;
1199                } else {
1200                    /*
1201                     * [ VC: Entity Declared ]
1202                     * In a document with an external subset or external
1203                     * parameter entities with "standalone='no'", ...
1204                     * ... The declaration of a parameter entity must precede
1205                     * any reference to it...
1206                     */
1207                    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1208                        ctxt->sax->warning(ctxt->userData,
1209                         "PEReference: %%%s; not found\n", name);
1210                    ctxt->valid = 0;
1211                }
1212            } else {
1213                if ((entity->type == XML_INTERNAL_PARAMETER_ENTITY) ||
1214                    (entity->type == XML_EXTERNAL_PARAMETER_ENTITY)) {
1215                    /*
1216                     * TODO !!!! handle the extra spaces added before and after
1217                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
1218                     * TODO !!!! Avoid quote processing in parameters value
1219                     * c.f. http://www.w3.org/TR/REC-xml#inliteral
1220                     */
1221                    input = xmlOldNewEntityInputStream(ctxt, entity);
1222                    xmlOldPushInput(ctxt, input);
1223                } else {
1224                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1225                        ctxt->sax->error(ctxt->userData,
1226                         "xmlHandlePEReference: %s is not a parameter entity\n",
1227                                         name);
1228                    ctxt->wellFormed = 0;
1229                }
1230            }
1231        } else {
1232            ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
1233            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1234                ctxt->sax->error(ctxt->userData,
1235                                 "xmlHandlePEReference: expecting ';'\n");
1236            ctxt->wellFormed = 0;
1237        }
1238        xmlFree(name);
1239    }
1240}
1241
1242/*
1243 * Macro used to grow the current buffer.
1244 */
1245#define growBuffer(buffer) {                                            \
1246    buffer##_size *= 2;                                                 \
1247    buffer = (xmlChar *)                                                \
1248                xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
1249    if (buffer == NULL) {                                               \
1250        perror("realloc failed");                                       \
1251        return(NULL);                                                   \
1252    }                                                                   \
1253}
1254
1255/**
1256 * xmlOldDecodeEntities:
1257 * @ctxt:  the parser context
1258 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1259 * @len:  the len to decode (in bytes !), -1 for no size limit
1260 * @end:  an end marker xmlChar, 0 if none
1261 * @end2:  an end marker xmlChar, 0 if none
1262 * @end3:  an end marker xmlChar, 0 if none
1263 *
1264 * [67] Reference ::= EntityRef | CharRef
1265 *
1266 * [69] PEReference ::= '%' Name ';'
1267 *
1268 * Returns A newly allocated string with the substitution done. The caller
1269 *      must deallocate it !
1270 */
1271static xmlChar *
1272xmlOldDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
1273                  xmlChar end, xmlChar  end2, xmlChar end3) {
1274    xmlChar *buffer = NULL;
1275    int buffer_size = 0;
1276    xmlChar *out = NULL;
1277
1278    xmlChar *current = NULL;
1279    xmlEntityPtr ent;
1280    int nbchars = 0;
1281    unsigned int max = (unsigned int) len;
1282    xmlChar cur;
1283
1284    /*
1285     * allocate a translation buffer.
1286     */
1287    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
1288    buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1289    if (buffer == NULL) {
1290        perror("xmlDecodeEntities: malloc failed");
1291        return(NULL);
1292    }
1293    out = buffer;
1294
1295    /*
1296     * Ok loop until we reach one of the ending char or a size limit.
1297     */
1298    cur = CUR;
1299    while ((nbchars < max) && (cur != end) &&
1300           (cur != end2) && (cur != end3)) {
1301
1302        if (cur == 0) break;
1303        if ((cur == '&') && (NXT(1) == '#')) {
1304            int val = xmlOldParseCharRef(ctxt);
1305            *out++ = val;
1306            nbchars += 3;
1307        } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
1308            ent = xmlOldParseEntityRef(ctxt);
1309            if ((ent != NULL) &&
1310                (ctxt->replaceEntities != 0)) {
1311                current = ent->content;
1312                while (*current != 0) {
1313                    *out++ = *current++;
1314                    if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1315                        int index = out - buffer;
1316
1317                        growBuffer(buffer);
1318                        out = &buffer[index];
1319                    }
1320                }
1321                nbchars += 3 + xmlStrlen(ent->name);
1322            } else if (ent != NULL) {
1323                int i = xmlStrlen(ent->name);
1324                const xmlChar *cur = ent->name;
1325
1326                nbchars += i + 2;
1327                *out++ = '&';
1328                if (out - buffer > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
1329                    int index = out - buffer;
1330
1331                    growBuffer(buffer);
1332                    out = &buffer[index];
1333                }
1334                for (;i > 0;i--)
1335                    *out++ = *cur++;
1336                *out++ = ';';
1337            }
1338        } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
1339            /*
1340             * a PEReference induce to switch the entity flow,
1341             * we break here to flush the current set of chars
1342             * parsed if any. We will be called back later.
1343             */
1344            if (nbchars != 0) break;
1345
1346            xmlOldParsePEReference(ctxt);
1347
1348            /*
1349             * Pop-up of finished entities.
1350             */
1351            while ((CUR == 0) && (ctxt->inputNr > 1))
1352                xmlOldPopInput(ctxt);
1353
1354            break;
1355        } else {
1356            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
1357            *out++ = cur;
1358            nbchars++;
1359            if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1360              int index = out - buffer;
1361             
1362              growBuffer(buffer);
1363              out = &buffer[index];
1364            }
1365            NEXT;
1366        }
1367        cur = CUR;
1368    }
1369    *out++ = 0;
1370    return(buffer);
1371}
1372
1373/**
1374 * xmlOldStringDecodeEntities:
1375 * @ctxt:  the parser context
1376 * @str:  the input string
1377 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1378 * @end:  an end marker xmlChar, 0 if none
1379 * @end2:  an end marker xmlChar, 0 if none
1380 * @end3:  an end marker xmlChar, 0 if none
1381 *
1382 * [67] Reference ::= EntityRef | CharRef
1383 *
1384 * [69] PEReference ::= '%' Name ';'
1385 *
1386 * Returns A newly allocated string with the substitution done. The caller
1387 *      must deallocate it !
1388 */
1389static xmlChar *
1390xmlOldStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
1391                        xmlChar end, xmlChar  end2, xmlChar end3) {
1392    xmlChar *buffer = NULL;
1393    int buffer_size = 0;
1394    xmlChar *out = NULL;
1395
1396    xmlChar *current = NULL;
1397    xmlEntityPtr ent;
1398    xmlChar cur;
1399
1400    /*
1401     * allocate a translation buffer.
1402     */
1403    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
1404    buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1405    if (buffer == NULL) {
1406        perror("xmlStringDecodeEntities: malloc failed");
1407        return(NULL);
1408    }
1409    out = buffer;
1410
1411    /*
1412     * Ok loop until we reach one of the ending char or a size limit.
1413     */
1414    cur = *str;
1415    while ((cur != 0) && (cur != end) &&
1416           (cur != end2) && (cur != end3)) {
1417
1418        if (cur == 0) break;
1419        if ((cur == '&') && (str[1] == '#')) {
1420            int val = xmlOldParseStringCharRef(ctxt, &str);
1421            if (val != 0)
1422                *out++ = val;
1423        } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
1424            ent = xmlOldParseStringEntityRef(ctxt, &str);
1425            if ((ent != NULL) &&
1426                (ctxt->replaceEntities != 0)) {
1427                current = ent->content;
1428                while (*current != 0) {
1429                    *out++ = *current++;
1430                    if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1431                        int index = out - buffer;
1432
1433                        growBuffer(buffer);
1434                        out = &buffer[index];
1435                    }
1436                }
1437            } else if (ent != NULL) {
1438                int i = xmlStrlen(ent->name);
1439                const xmlChar *cur = ent->name;
1440
1441                *out++ = '&';
1442                if (out - buffer > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
1443                    int index = out - buffer;
1444
1445                    growBuffer(buffer);
1446                    out = &buffer[index];
1447                }
1448                for (;i > 0;i--)
1449                    *out++ = *cur++;
1450                *out++ = ';';
1451            }
1452        } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
1453            ent = xmlOldParseStringPEReference(ctxt, &str);
1454            if (ent != NULL) {
1455                current = ent->content;
1456                while (*current != 0) {
1457                    *out++ = *current++;
1458                    if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1459                        int index = out - buffer;
1460
1461                        growBuffer(buffer);
1462                        out = &buffer[index];
1463                    }
1464                }
1465            }
1466        } else {
1467            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
1468            *out++ = cur;
1469            if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1470              int index = out - buffer;
1471             
1472              growBuffer(buffer);
1473              out = &buffer[index];
1474            }
1475            str++;
1476        }
1477        cur = *str;
1478    }
1479    *out = 0;
1480    return(buffer);
1481}
1482
1483/************************************************************************
1484 *                                                                      *
1485 *              Commodity functions, cleanup needed ?                   *
1486 *                                                                      *
1487 ************************************************************************/
1488
1489/**
1490 * areBlanksOld:
1491 * @ctxt:  an XML parser context
1492 * @str:  a xmlChar *
1493 * @len:  the size of @str
1494 *
1495 * Is this a sequence of blank chars that one can ignore ?
1496 *
1497 * Returns 1 if ignorable 0 otherwise.
1498 */
1499
1500static int areBlanksOld(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1501    int i, ret;
1502    xmlNodePtr lastChild;
1503
1504    /*
1505     * Check that the string is made of blanks
1506     */
1507    for (i = 0;i < len;i++)
1508        if (!(IS_BLANK(str[i]))) return(0);
1509
1510    /*
1511     * Look if the element is mixed content in the Dtd if available
1512     */
1513    if (ctxt->myDoc != NULL) {
1514        ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
1515        if (ret == 0) return(1);
1516        if (ret == 1) return(0);
1517    }
1518
1519    /*
1520     * Do we allow an heuristic on white space
1521     */
1522    if (ctxt->keepBlanks)
1523        return(0);
1524    if (CUR != '<') return(0);
1525    if (ctxt->node == NULL) return(0);
1526    if ((ctxt->node->childs == NULL) &&
1527        (CUR == '<') && (NXT(1) == '/')) return(0);
1528
1529    lastChild = xmlGetLastChild(ctxt->node);
1530    if (lastChild == NULL) {
1531        if (ctxt->node->content != NULL) return(0);
1532    } else if (xmlNodeIsText(lastChild))
1533        return(0);
1534    else if ((ctxt->node->childs != NULL) &&
1535             (xmlNodeIsText(ctxt->node->childs)))
1536        return(0);
1537    return(1);
1538}
1539
1540/**
1541 * xmlOldHandleEntity:
1542 * @ctxt:  an XML parser context
1543 * @entity:  an XML entity pointer.
1544 *
1545 * Default handling of defined entities, when should we define a new input
1546 * stream ? When do we just handle that as a set of chars ?
1547 *
1548 * OBSOLETE: to be removed at some point.
1549 */
1550
1551static void
1552xmlOldHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1553    int len;
1554    xmlParserInputPtr input;
1555
1556    if (entity->content == NULL) {
1557        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1558        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1559            ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
1560                       entity->name);
1561        ctxt->wellFormed = 0;
1562        return;
1563    }
1564    len = xmlStrlen(entity->content);
1565    if (len <= 2) goto handle_as_char;
1566
1567    /*
1568     * Redefine its content as an input stream.
1569     */
1570    input = xmlOldNewEntityInputStream(ctxt, entity);
1571    xmlOldPushInput(ctxt, input);
1572    return;
1573
1574handle_as_char:
1575    /*
1576     * Just handle the content as a set of chars.
1577     */
1578    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
1579        ctxt->sax->characters(ctxt->userData, entity->content, len);
1580
1581}
1582
1583/************************************************************************
1584 *                                                                      *
1585 *              Extra stuff for namespace support                       *
1586 *      Relates to http://www.w3.org/TR/WD-xml-names                    *
1587 *                                                                      *
1588 ************************************************************************/
1589
1590/**
1591 * xmlOldNamespaceParseNCName:
1592 * @ctxt:  an XML parser context
1593 *
1594 * parse an XML namespace name.
1595 *
1596 * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
1597 *
1598 * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
1599 *                       CombiningChar | Extender
1600 *
1601 * Returns the namespace name or NULL
1602 */
1603
1604static xmlChar *
1605xmlOldNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
1606    xmlChar buf[XML_MAX_NAMELEN];
1607    int len = 0;
1608
1609    if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
1610
1611    while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1612           (CUR == '.') || (CUR == '-') ||
1613           (CUR == '_') ||
1614           (IS_COMBINING(CUR)) ||
1615           (IS_EXTENDER(CUR))) {
1616        buf[len++] = CUR;
1617        NEXT;
1618        if (len >= XML_MAX_NAMELEN) {
1619            fprintf(stderr,
1620               "xmlNamespaceParseNCName: reached XML_MAX_NAMELEN limit\n");
1621            while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1622                   (CUR == '.') || (CUR == '-') ||
1623                   (CUR == '_') ||
1624                   (IS_COMBINING(CUR)) ||
1625                   (IS_EXTENDER(CUR)))
1626                 NEXT;
1627            break;
1628        }
1629    }
1630    return(xmlStrndup(buf, len));
1631}
1632
1633/**
1634 * xmlOldNamespaceParseQName:
1635 * @ctxt:  an XML parser context
1636 * @prefix:  a xmlChar **
1637 *
1638 * parse an XML qualified name
1639 *
1640 * [NS 5] QName ::= (Prefix ':')? LocalPart
1641 *
1642 * [NS 6] Prefix ::= NCName
1643 *
1644 * [NS 7] LocalPart ::= NCName
1645 *
1646 * Returns the local part, and prefix is updated
1647 *   to get the Prefix if any.
1648 */
1649
1650static xmlChar *
1651xmlOldNamespaceParseQName(xmlParserCtxtPtr ctxt, xmlChar **prefix) {
1652    xmlChar *ret = NULL;
1653
1654    *prefix = NULL;
1655    ret = xmlOldNamespaceParseNCName(ctxt);
1656    if (CUR == ':') {
1657        *prefix = ret;
1658        NEXT;
1659        ret = xmlOldNamespaceParseNCName(ctxt);
1660    }
1661
1662    return(ret);
1663}
1664
1665/**
1666 * xmlOldParseQuotedString:
1667 * @ctxt:  an XML parser context
1668 *
1669 * [OLD] Parse and return a string between quotes or doublequotes
1670 * To be removed at next drop of binary compatibility
1671 *
1672 * Returns the string parser or NULL.
1673 */
1674static xmlChar *
1675xmlOldParseQuotedString(xmlParserCtxtPtr ctxt) {
1676    xmlChar *buf = NULL;
1677    int len = 0;
1678    int size = XML_PARSER_BUFFER_SIZE;
1679    xmlChar c;
1680
1681    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
1682    if (buf == NULL) {
1683        fprintf(stderr, "malloc of %d byte failed\n", size);
1684        return(NULL);
1685    }
1686    if (CUR == '"') {
1687        NEXT;
1688        c = CUR;
1689        while (IS_CHAR(c) && (c != '"')) {
1690            if (len + 1 >= size) {
1691                size *= 2;
1692                buf = xmlRealloc(buf, size * sizeof(xmlChar));
1693                if (buf == NULL) {
1694                    fprintf(stderr, "realloc of %d byte failed\n", size);
1695                    return(NULL);
1696                }
1697            }
1698            buf[len++] = c;
1699            NEXT;
1700            c = CUR;
1701        }
1702        if (c != '"') {
1703            ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1704            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1705                ctxt->sax->error(ctxt->userData,
1706                                 "String not closed \"%.50s\"\n", buf);
1707            ctxt->wellFormed = 0;
1708        } else {
1709            NEXT;
1710        }
1711    } else if (CUR == '\''){
1712        NEXT;
1713        c = CUR;
1714        while (IS_CHAR(c) && (c != '\'')) {
1715            if (len + 1 >= size) {
1716                size *= 2;
1717                buf = xmlRealloc(buf, size * sizeof(xmlChar));
1718                if (buf == NULL) {
1719                    fprintf(stderr, "realloc of %d byte failed\n", size);
1720                    return(NULL);
1721                }
1722            }
1723            buf[len++] = c;
1724            NEXT;
1725            c = CUR;
1726        }
1727        if (CUR != '\'') {
1728            ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1729            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1730                ctxt->sax->error(ctxt->userData,
1731                                 "String not closed \"%.50s\"\n", buf);
1732            ctxt->wellFormed = 0;
1733        } else {
1734            NEXT;
1735        }
1736    }
1737    return(buf);
1738}
1739
1740/**
1741 * xmlOldParseNamespace:
1742 * @ctxt:  an XML parser context
1743 *
1744 * [OLD] xmlOldParseNamespace: parse specific PI '<?namespace ...' constructs.
1745 *
1746 * This is what the older xml-name Working Draft specified, a bunch of
1747 * other stuff may still rely on it, so support is still here as
1748 * if it was declared on the root of the Tree:-(
1749 *
1750 * To be removed at next drop of binary compatibility
1751 */
1752
1753static void
1754xmlOldParseNamespace(xmlParserCtxtPtr ctxt) {
1755    xmlChar *href = NULL;
1756    xmlChar *prefix = NULL;
1757    int garbage = 0;
1758
1759    /*
1760     * We just skipped "namespace" or "xml:namespace"
1761     */
1762    SKIP_BLANKS;
1763
1764    while (IS_CHAR(CUR) && (CUR != '>')) {
1765        /*
1766         * We can have "ns" or "prefix" attributes
1767         * Old encoding as 'href' or 'AS' attributes is still supported
1768         */
1769        if ((CUR == 'n') && (NXT(1) == 's')) {
1770            garbage = 0;
1771            SKIP(2);
1772            SKIP_BLANKS;
1773
1774            if (CUR != '=') continue;
1775            NEXT;
1776            SKIP_BLANKS;
1777
1778            href = xmlOldParseQuotedString(ctxt);
1779            SKIP_BLANKS;
1780        } else if ((CUR == 'h') && (NXT(1) == 'r') &&
1781            (NXT(2) == 'e') && (NXT(3) == 'f')) {
1782            garbage = 0;
1783            SKIP(4);
1784            SKIP_BLANKS;
1785
1786            if (CUR != '=') continue;
1787            NEXT;
1788            SKIP_BLANKS;
1789
1790            href = xmlOldParseQuotedString(ctxt);
1791            SKIP_BLANKS;
1792        } else if ((CUR == 'p') && (NXT(1) == 'r') &&
1793                   (NXT(2) == 'e') && (NXT(3) == 'f') &&
1794                   (NXT(4) == 'i') && (NXT(5) == 'x')) {
1795            garbage = 0;
1796            SKIP(6);
1797            SKIP_BLANKS;
1798
1799            if (CUR != '=') continue;
1800            NEXT;
1801            SKIP_BLANKS;
1802
1803            prefix = xmlOldParseQuotedString(ctxt);
1804            SKIP_BLANKS;
1805        } else if ((CUR == 'A') && (NXT(1) == 'S')) {
1806            garbage = 0;
1807            SKIP(2);
1808            SKIP_BLANKS;
1809
1810            if (CUR != '=') continue;
1811            NEXT;
1812            SKIP_BLANKS;
1813
1814            prefix = xmlOldParseQuotedString(ctxt);
1815            SKIP_BLANKS;
1816        } else if ((CUR == '?') && (NXT(1) == '>')) {
1817            garbage = 0;
1818            NEXT;
1819        } else {
1820            /*
1821             * Found garbage when parsing the namespace
1822             */
1823            if (!garbage) {
1824                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1825                    ctxt->sax->error(ctxt->userData,
1826                                     "xmlParseNamespace found garbage\n");
1827            }
1828            ctxt->errNo = XML_ERR_NS_DECL_ERROR;
1829            ctxt->wellFormed = 0;
1830            NEXT;
1831        }
1832    }
1833
1834    MOVETO_ENDTAG(CUR_PTR);
1835    NEXT;
1836
1837    /*
1838     * Register the DTD.
1839    if (href != NULL)
1840        if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
1841            ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
1842     */
1843
1844    if (prefix != NULL) xmlFree(prefix);
1845    if (href != NULL) xmlFree(href);
1846}
1847
1848/************************************************************************
1849 *                                                                      *
1850 *                      The parser itself                               *
1851 *      Relates to http://www.w3.org/TR/REC-xml                         *
1852 *                                                                      *
1853 ************************************************************************/
1854
1855/**
1856 * xmlOldScanName:
1857 * @ctxt:  an XML parser context
1858 *
1859 * Trickery: parse an XML name but without consuming the input flow
1860 * Needed for rollback cases.
1861 *
1862 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1863 *                  CombiningChar | Extender
1864 *
1865 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1866 *
1867 * [6] Names ::= Name (S Name)*
1868 *
1869 * Returns the Name parsed or NULL
1870 */
1871
1872static xmlChar *
1873xmlOldScanName(xmlParserCtxtPtr ctxt) {
1874    xmlChar buf[XML_MAX_NAMELEN];
1875    int len = 0;
1876
1877    GROW;
1878    if (!IS_LETTER(CUR) && (CUR != '_') &&
1879        (CUR != ':')) {
1880        return(NULL);
1881    }
1882
1883    while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
1884           (NXT(len) == '.') || (NXT(len) == '-') ||
1885           (NXT(len) == '_') || (NXT(len) == ':') ||
1886           (IS_COMBINING(NXT(len))) ||
1887           (IS_EXTENDER(NXT(len)))) {
1888        buf[len] = NXT(len);
1889        len++;
1890        if (len >= XML_MAX_NAMELEN) {
1891            fprintf(stderr,
1892               "xmlScanName: reached XML_MAX_NAMELEN limit\n");
1893            while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
1894                   (NXT(len) == '.') || (NXT(len) == '-') ||
1895                   (NXT(len) == '_') || (NXT(len) == ':') ||
1896                   (IS_COMBINING(NXT(len))) ||
1897                   (IS_EXTENDER(NXT(len))))
1898                 len++;
1899            break;
1900        }
1901    }
1902    return(xmlStrndup(buf, len));
1903}
1904
1905/**
1906 * xmlOldParseName:
1907 * @ctxt:  an XML parser context
1908 *
1909 * parse an XML name.
1910 *
1911 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1912 *                  CombiningChar | Extender
1913 *
1914 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1915 *
1916 * [6] Names ::= Name (S Name)*
1917 *
1918 * Returns the Name parsed or NULL
1919 */
1920
1921static xmlChar *
1922xmlOldParseName(xmlParserCtxtPtr ctxt) {
1923    xmlChar buf[XML_MAX_NAMELEN];
1924    int len = 0;
1925    xmlChar cur;
1926
1927    GROW;
1928    cur = CUR;
1929    if (!IS_LETTER(cur) && (cur != '_') &&
1930        (cur != ':')) {
1931        return(NULL);
1932    }
1933
1934    while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
1935           (cur == '.') || (cur == '-') ||
1936           (cur == '_') || (cur == ':') ||
1937           (IS_COMBINING(cur)) ||
1938           (IS_EXTENDER(cur))) {
1939        buf[len++] = cur;
1940        NEXT;
1941        cur = CUR;
1942        if (len >= XML_MAX_NAMELEN) {
1943            fprintf(stderr,
1944               "xmlParseName: reached XML_MAX_NAMELEN limit\n");
1945            while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
1946                   (cur == '.') || (cur == '-') ||
1947                   (cur == '_') || (cur == ':') ||
1948                   (IS_COMBINING(cur)) ||
1949                   (IS_EXTENDER(cur))) {
1950                NEXT;
1951                cur = CUR;
1952            }
1953            break;
1954        }
1955    }
1956    return(xmlStrndup(buf, len));
1957}
1958
1959/**
1960 * xmlOldParseStringName:
1961 * @ctxt:  an XML parser context
1962 * @str:  a pointer to an index in the string
1963 *
1964 * parse an XML name.
1965 *
1966 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1967 *                  CombiningChar | Extender
1968 *
1969 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1970 *
1971 * [6] Names ::= Name (S Name)*
1972 *
1973 * Returns the Name parsed or NULL. The str pointer
1974 * is updated to the current location in the string.
1975 */
1976
1977static xmlChar *
1978xmlOldParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
1979    const xmlChar *ptr;
1980    const xmlChar *start;
1981    xmlChar cur;
1982
1983    if ((str == NULL) || (*str == NULL)) return(NULL);
1984
1985    start = ptr = *str;
1986    cur = *ptr;
1987    if (!IS_LETTER(cur) && (cur != '_') &&
1988        (cur != ':')) {
1989        return(NULL);
1990    }
1991
1992    while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
1993           (cur == '.') || (cur == '-') ||
1994           (cur == '_') || (cur == ':') ||
1995           (IS_COMBINING(cur)) ||
1996           (IS_EXTENDER(cur))) {
1997        ptr++;
1998        cur = *ptr;
1999    }
2000    *str = ptr;
2001    return(xmlStrndup(start, ptr - start ));
2002}
2003
2004/**
2005 * xmlOldParseNmtoken:
2006 * @ctxt:  an XML parser context
2007 *
2008 * parse an XML Nmtoken.
2009 *
2010 * [7] Nmtoken ::= (NameChar)+
2011 *
2012 * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
2013 *
2014 * Returns the Nmtoken parsed or NULL
2015 */
2016
2017static xmlChar *
2018xmlOldParseNmtoken(xmlParserCtxtPtr ctxt) {
2019    xmlChar buf[XML_MAX_NAMELEN];
2020    int len = 0;
2021
2022    GROW;
2023    while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2024           (CUR == '.') || (CUR == '-') ||
2025           (CUR == '_') || (CUR == ':') ||
2026           (IS_COMBINING(CUR)) ||
2027           (IS_EXTENDER(CUR))) {
2028        buf[len++] = CUR;
2029        NEXT;
2030        if (len >= XML_MAX_NAMELEN) {
2031            fprintf(stderr,
2032               "xmlParseNmtoken: reached XML_MAX_NAMELEN limit\n");
2033            while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2034                   (CUR == '.') || (CUR == '-') ||
2035                   (CUR == '_') || (CUR == ':') ||
2036                   (IS_COMBINING(CUR)) ||
2037                   (IS_EXTENDER(CUR)))
2038                 NEXT;
2039            break;
2040        }
2041    }
2042    return(xmlStrndup(buf, len));
2043}
2044
2045/**
2046 * xmlOldParseEntityValue:
2047 * @ctxt:  an XML parser context
2048 * @orig:  if non-NULL store a copy of the original entity value
2049 *
2050 * parse a value for ENTITY decl.
2051 *
2052 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
2053 *                     "'" ([^%&'] | PEReference | Reference)* "'"
2054 *
2055 * Returns the EntityValue parsed with reference substitued or NULL
2056 */
2057
2058static xmlChar *
2059xmlOldParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
2060    xmlChar *buf = NULL;
2061    int len = 0;
2062    int size = XML_PARSER_BUFFER_SIZE;
2063    xmlChar c;
2064    xmlChar stop;
2065    xmlChar *ret = NULL;
2066    xmlParserInputPtr input;
2067
2068    if (CUR == '"') stop = '"';
2069    else if (CUR == '\'') stop = '\'';
2070    else {
2071        ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
2072        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2073            ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
2074        ctxt->wellFormed = 0;
2075        return(NULL);
2076    }
2077    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2078    if (buf == NULL) {
2079        fprintf(stderr, "malloc of %d byte failed\n", size);
2080        return(NULL);
2081    }
2082
2083    /*
2084     * The content of the entity definition is copied in a buffer.
2085     */
2086
2087    ctxt->instate = XML_PARSER_ENTITY_VALUE;
2088    input = ctxt->input;
2089    GROW;
2090    NEXT;
2091    c = CUR;
2092    /*
2093     * NOTE: 4.4.5 Included in Literal
2094     * When a parameter entity reference appears in a literal entity
2095     * value, ... a single or double quote character in the replacement
2096     * text is always treated as a normal data character and will not
2097     * terminate the literal.
2098     * In practice it means we stop the loop only when back at parsing
2099     * the initial entity and the quote is found
2100     */
2101    while (IS_CHAR(c) && ((c != stop) || (ctxt->input != input))) {
2102        if (len + 1 >= size) {
2103            size *= 2;
2104            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2105            if (buf == NULL) {
2106                fprintf(stderr, "realloc of %d byte failed\n", size);
2107                return(NULL);
2108            }
2109        }
2110        buf[len++] = c;
2111        NEXT;
2112        /*
2113         * Pop-up of finished entities.
2114         */
2115        while ((CUR == 0) && (ctxt->inputNr > 1))
2116            xmlOldPopInput(ctxt);
2117        c = CUR;
2118        if (c == 0) {
2119            GROW;
2120            c = CUR;
2121        }
2122    }
2123    buf[len] = 0;
2124
2125    /*
2126     * Then PEReference entities are substituted.
2127     */
2128    if (c != stop) {
2129        ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
2130        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2131            ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
2132        ctxt->wellFormed = 0;
2133    } else {
2134        NEXT;
2135        /*
2136         * NOTE: 4.4.7 Bypassed
2137         * When a general entity reference appears in the EntityValue in
2138         * an entity declaration, it is bypassed and left as is.
2139         * so XML_SUBSTITUTE_REF is not set.
2140         */
2141        ret = xmlOldStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
2142                                      0, 0, 0);
2143        if (orig != NULL)
2144            *orig = buf;
2145        else
2146            xmlFree(buf);
2147    }
2148   
2149    return(ret);
2150}
2151
2152/**
2153 * xmlOldParseAttValue:
2154 * @ctxt:  an XML parser context
2155 *
2156 * parse a value for an attribute
2157 * Note: the parser won't do substitution of entities here, this
2158 * will be handled later in xmlStringGetNodeList
2159 *
2160 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
2161 *                   "'" ([^<&'] | Reference)* "'"
2162 *
2163 * 3.3.3 Attribute-Value Normalization:
2164 * Before the value of an attribute is passed to the application or
2165 * checked for validity, the XML processor must normalize it as follows:
2166 * - a character reference is processed by appending the referenced
2167 *   character to the attribute value
2168 * - an entity reference is processed by recursively processing the
2169 *   replacement text of the entity
2170 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
2171 *   appending #x20 to the normalized value, except that only a single
2172 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
2173 *   parsed entity or the literal entity value of an internal parsed entity
2174 * - other characters are processed by appending them to the normalized value
2175 * If the declared value is not CDATA, then the XML processor must further
2176 * process the normalized attribute value by discarding any leading and
2177 * trailing space (#x20) characters, and by replacing sequences of space
2178 * (#x20) characters by a single space (#x20) character. 
2179 * All attributes for which no declaration has been read should be treated
2180 * by a non-validating parser as if declared CDATA.
2181 *
2182 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
2183 */
2184
2185static xmlChar *
2186xmlOldParseAttValue(xmlParserCtxtPtr ctxt) {
2187    xmlChar limit = 0;
2188    xmlChar *buffer = NULL;
2189    int buffer_size = 0;
2190    xmlChar *out = NULL;
2191
2192    xmlChar *current = NULL;
2193    xmlEntityPtr ent;
2194    xmlChar cur;
2195
2196
2197    SHRINK;
2198    if (CUR == '"') {
2199        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
2200        limit = '"';
2201        NEXT;
2202    } else if (CUR == '\'') {
2203        limit = '\'';
2204        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
2205        NEXT;
2206    } else {
2207        ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
2208        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2209            ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
2210        ctxt->wellFormed = 0;
2211        return(NULL);
2212    }
2213   
2214    /*
2215     * allocate a translation buffer.
2216     */
2217    buffer_size = XML_PARSER_BUFFER_SIZE;
2218    buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
2219    if (buffer == NULL) {
2220        perror("xmlParseAttValue: malloc failed");
2221        return(NULL);
2222    }
2223    out = buffer;
2224
2225    /*
2226     * Ok loop until we reach one of the ending char or a size limit.
2227     */
2228    cur = CUR;
2229    while ((ctxt->token != 0) ||
2230           ((cur != limit) && (cur != '<'))) {
2231        if (cur == 0) break;
2232        if (ctxt->token == '&') {
2233            /*
2234             * The reparsing will be done in xmlStringGetNodeList()
2235             * called by the attribute() function in SAX.c
2236             */
2237            static xmlChar quote[6] = "&#38;";
2238
2239            if (out - buffer > buffer_size - 10) {
2240                int index = out - buffer;
2241
2242                growBuffer(buffer);
2243                out = &buffer[index];
2244            }
2245            current = &quote[0];
2246            while (*current != 0) { /* non input consuming */
2247                *out++ = *current++;
2248            }
2249            NEXT;
2250        } else if ((cur == '&') && (NXT(1) == '#')) {
2251            int val = xmlOldParseCharRef(ctxt);
2252            *out++ = val;
2253            if (out - buffer > buffer_size - 10) {
2254                int index = out - buffer;
2255
2256                growBuffer(buffer);
2257                out = &buffer[index];
2258            }
2259        } else if (cur == '&') {
2260            ent = xmlOldParseEntityRef(ctxt);
2261            if ((ent != NULL) &&
2262                (ctxt->replaceEntities != 0)) {
2263                current = ent->content;
2264                while (*current != 0) {
2265                    *out++ = *current++;
2266                    if (out - buffer > buffer_size - 10) {
2267                        int index = out - buffer;
2268
2269                        growBuffer(buffer);
2270                        out = &buffer[index];
2271                    }
2272                }
2273            } else if (ent != NULL) {
2274                int i = xmlStrlen(ent->name);
2275                const xmlChar *cur = ent->name;
2276
2277                *out++ = '&';
2278                while (out - buffer > buffer_size - i - 10) {
2279                    int index = out - buffer;
2280
2281                    growBuffer(buffer);
2282                    out = &buffer[index];
2283                }
2284                for (;i > 0;i--)
2285                    *out++ = *cur++;
2286                *out++ = ';';
2287            }
2288        } else {
2289            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
2290            if ((ctxt->token == 0) && ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9))) {
2291                *out++ = 0x20;
2292                if (out - buffer > buffer_size - 10) {
2293                  int index = out - buffer;
2294                 
2295                  growBuffer(buffer);
2296                  out = &buffer[index];
2297                }
2298            } else {
2299                *out++ = cur;
2300                if (out - buffer > buffer_size - 10) {
2301                  int index = out - buffer;
2302                 
2303                  growBuffer(buffer);
2304                  out = &buffer[index];
2305                }
2306            }
2307            NEXT;
2308        }
2309        cur = CUR;
2310    }
2311    *out++ = 0;
2312    if (CUR == '<') {
2313        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2314            ctxt->sax->error(ctxt->userData,
2315               "Unescaped '<' not allowed in attributes values\n");
2316        ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
2317        ctxt->wellFormed = 0;
2318    } else if (CUR != limit) {
2319        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2320            ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
2321        ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
2322        ctxt->wellFormed = 0;
2323    } else
2324        NEXT;
2325    return(buffer);
2326}
2327
2328/**
2329 * xmlOldParseSystemLiteral:
2330 * @ctxt:  an XML parser context
2331 *
2332 * parse an XML Literal
2333 *
2334 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
2335 *
2336 * Returns the SystemLiteral parsed or NULL
2337 */
2338
2339static xmlChar *
2340xmlOldParseSystemLiteral(xmlParserCtxtPtr ctxt) {
2341    xmlChar *buf = NULL;
2342    int len = 0;
2343    int size = XML_PARSER_BUFFER_SIZE;
2344    xmlChar cur;
2345    xmlChar stop;
2346
2347    SHRINK;
2348    if (CUR == '"') {
2349        NEXT;
2350        stop = '"';
2351    } else if (CUR == '\'') {
2352        NEXT;
2353        stop = '\'';
2354    } else {
2355        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2356            ctxt->sax->error(ctxt->userData,
2357                             "SystemLiteral \" or ' expected\n");
2358        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2359        ctxt->wellFormed = 0;
2360        return(NULL);
2361    }
2362   
2363    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2364    if (buf == NULL) {
2365        fprintf(stderr, "malloc of %d byte failed\n", size);
2366        return(NULL);
2367    }
2368    cur = CUR;
2369    while ((IS_CHAR(cur)) && (cur != stop)) {
2370        if (len + 1 >= size) {
2371            size *= 2;
2372            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2373            if (buf == NULL) {
2374                fprintf(stderr, "realloc of %d byte failed\n", size);
2375                return(NULL);
2376            }
2377        }
2378        buf[len++] = cur;
2379        NEXT;
2380        cur = CUR;
2381        if (cur == 0) {
2382            GROW;
2383            SHRINK;
2384            cur = CUR;
2385        }
2386    }
2387    buf[len] = 0;
2388    if (!IS_CHAR(cur)) {
2389        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2390            ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
2391        ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2392        ctxt->wellFormed = 0;
2393    } else {
2394        NEXT;
2395    }
2396    return(buf);
2397}
2398
2399/**
2400 * xmlOldParsePubidLiteral:
2401 * @ctxt:  an XML parser context
2402 *
2403 * parse an XML public literal
2404 *
2405 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2406 *
2407 * Returns the PubidLiteral parsed or NULL.
2408 */
2409
2410static xmlChar *
2411xmlOldParsePubidLiteral(xmlParserCtxtPtr ctxt) {
2412    xmlChar *buf = NULL;
2413    int len = 0;
2414    int size = XML_PARSER_BUFFER_SIZE;
2415    xmlChar cur;
2416    xmlChar stop;
2417
2418    SHRINK;
2419    if (CUR == '"') {
2420        NEXT;
2421        stop = '"';
2422    } else if (CUR == '\'') {
2423        NEXT;
2424        stop = '\'';
2425    } else {
2426        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2427            ctxt->sax->error(ctxt->userData,
2428                             "SystemLiteral \" or ' expected\n");
2429        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2430        ctxt->wellFormed = 0;
2431        return(NULL);
2432    }
2433    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2434    if (buf == NULL) {
2435        fprintf(stderr, "malloc of %d byte failed\n", size);
2436        return(NULL);
2437    }
2438    cur = CUR;
2439    while ((IS_PUBIDCHAR(cur)) && (cur != stop)) {
2440        if (len + 1 >= size) {
2441            size *= 2;
2442            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2443            if (buf == NULL) {
2444                fprintf(stderr, "realloc of %d byte failed\n", size);
2445                return(NULL);
2446            }
2447        }
2448        buf[len++] = cur;
2449        NEXT;
2450        cur = CUR;
2451        if (cur == 0) {
2452            GROW;
2453            SHRINK;
2454            cur = CUR;
2455        }
2456    }
2457    buf[len] = 0;
2458    if (cur != stop) {
2459        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2460            ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
2461        ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2462        ctxt->wellFormed = 0;
2463    } else {
2464        NEXT;
2465    }
2466    return(buf);
2467}
2468
2469/**
2470 * xmlOldParseCharData:
2471 * @ctxt:  an XML parser context
2472 * @cdata:  int indicating whether we are within a CDATA section
2473 *
2474 * parse a CharData section.
2475 * if we are within a CDATA section ']]>' marks an end of section.
2476 *
2477 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2478 */
2479
2480static void
2481xmlOldParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
2482    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE];
2483    int nbchar = 0;
2484    xmlChar cur;
2485
2486    SHRINK;
2487    cur = CUR;
2488    while (((cur != '<') || (ctxt->token == '<')) &&
2489           ((cur != '&') || (ctxt->token == '&')) &&
2490           (IS_CHAR(cur))) {
2491        if ((cur == ']') && (NXT(1) == ']') &&
2492            (NXT(2) == '>')) {
2493            if (cdata) break;
2494            else {
2495                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2496                    ctxt->sax->warning(ctxt->userData,
2497                       "Sequence ']]>' not allowed in content\n");
2498                ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
2499            }
2500        }
2501        buf[nbchar++] = CUR;
2502        if (nbchar == XML_PARSER_BIG_BUFFER_SIZE) {
2503            /*
2504             * Ok the segment is to be consumed as chars.
2505             */
2506            if (ctxt->sax != NULL) {
2507                if (areBlanksOld(ctxt, buf, nbchar)) {
2508                    if (ctxt->sax->ignorableWhitespace != NULL)
2509                        ctxt->sax->ignorableWhitespace(ctxt->userData,
2510                                                       buf, nbchar);
2511                } else {
2512                    if (ctxt->sax->characters != NULL)
2513                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
2514                }
2515            }
2516            nbchar = 0;
2517        }
2518        NEXT;
2519        cur = CUR;
2520    }
2521    if (nbchar != 0) {
2522        /*
2523         * Ok the segment is to be consumed as chars.
2524         */
2525        if (ctxt->sax != NULL) {
2526            if (areBlanksOld(ctxt, buf, nbchar)) {
2527                if (ctxt->sax->ignorableWhitespace != NULL)
2528                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2529            } else {
2530                if (ctxt->sax->characters != NULL)
2531                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
2532            }
2533        }
2534    }
2535}
2536
2537/**
2538 * xmlOldParseExternalID:
2539 * @ctxt:  an XML parser context
2540 * @publicID:  a xmlChar** receiving PubidLiteral
2541 * @strict: indicate whether we should restrict parsing to only
2542 *          production [75], see NOTE below
2543 *
2544 * Parse an External ID or a Public ID
2545 *
2546 * NOTE: Productions [75] and [83] interract badly since [75] can generate
2547 *       'PUBLIC' S PubidLiteral S SystemLiteral
2548 *
2549 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2550 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
2551 *
2552 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2553 *
2554 * Returns the function returns SystemLiteral and in the second
2555 *                case publicID receives PubidLiteral, is strict is off
2556 *                it is possible to return NULL and have publicID set.
2557 */
2558
2559static xmlChar *
2560xmlOldParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2561    xmlChar *URI = NULL;
2562
2563    SHRINK;
2564    if ((CUR == 'S') && (NXT(1) == 'Y') &&
2565         (NXT(2) == 'S') && (NXT(3) == 'T') &&
2566         (NXT(4) == 'E') && (NXT(5) == 'M')) {
2567        SKIP(6);
2568        if (!IS_BLANK(CUR)) {
2569            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2570                ctxt->sax->error(ctxt->userData,
2571                    "Space required after 'SYSTEM'\n");
2572            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2573            ctxt->wellFormed = 0;
2574        }
2575        SKIP_BLANKS;
2576        URI = xmlOldParseSystemLiteral(ctxt);
2577        if (URI == NULL) {
2578            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2579                ctxt->sax->error(ctxt->userData,
2580                  "xmlParseExternalID: SYSTEM, no URI\n");
2581            ctxt->errNo = XML_ERR_URI_REQUIRED;
2582            ctxt->wellFormed = 0;
2583        }
2584    } else if ((CUR == 'P') && (NXT(1) == 'U') &&
2585               (NXT(2) == 'B') && (NXT(3) == 'L') &&
2586               (NXT(4) == 'I') && (NXT(5) == 'C')) {
2587        SKIP(6);
2588        if (!IS_BLANK(CUR)) {
2589            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2590                ctxt->sax->error(ctxt->userData,
2591                    "Space required after 'PUBLIC'\n");
2592            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2593            ctxt->wellFormed = 0;
2594        }
2595        SKIP_BLANKS;
2596        *publicID = xmlOldParsePubidLiteral(ctxt);
2597        if (*publicID == NULL) {
2598            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2599                ctxt->sax->error(ctxt->userData,
2600                  "xmlParseExternalID: PUBLIC, no Public Identifier\n");
2601            ctxt->errNo = XML_ERR_PUBID_REQUIRED;
2602            ctxt->wellFormed = 0;
2603        }
2604        if (strict) {
2605            /*
2606             * We don't handle [83] so "S SystemLiteral" is required.
2607             */
2608            if (!IS_BLANK(CUR)) {
2609                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2610                    ctxt->sax->error(ctxt->userData,
2611                        "Space required after the Public Identifier\n");
2612                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2613                ctxt->wellFormed = 0;
2614            }
2615        } else {
2616            /*
2617             * We handle [83] so we return immediately, if
2618             * "S SystemLiteral" is not detected. From a purely parsing
2619             * point of view that's a nice mess.
2620             */
2621            const xmlChar *ptr;
2622            GROW;
2623
2624            ptr = CUR_PTR;
2625            if (!IS_BLANK(*ptr)) return(NULL);
2626           
2627            while (IS_BLANK(*ptr)) ptr++;
2628            if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
2629        }
2630        SKIP_BLANKS;
2631        URI = xmlOldParseSystemLiteral(ctxt);
2632        if (URI == NULL) {
2633            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2634                ctxt->sax->error(ctxt->userData,
2635                   "xmlParseExternalID: PUBLIC, no URI\n");
2636            ctxt->errNo = XML_ERR_URI_REQUIRED;
2637            ctxt->wellFormed = 0;
2638        }
2639    }
2640    return(URI);
2641}
2642
2643/**
2644 * xmlOldParseComment:
2645 * @ctxt:  an XML parser context
2646 *
2647 * Skip an XML (SGML) comment <!-- .... -->
2648 *  The spec says that "For compatibility, the string "--" (double-hyphen)
2649 *  must not occur within comments. "
2650 *
2651 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
2652 */
2653static void
2654xmlOldParseComment(xmlParserCtxtPtr ctxt) {
2655    xmlChar *buf = NULL;
2656    int len = 0;
2657    int size = XML_PARSER_BUFFER_SIZE;
2658    xmlChar q;
2659    xmlChar r;
2660    xmlChar cur;
2661    xmlParserInputState state;
2662
2663    /*
2664     * Check that there is a comment right here.
2665     */
2666    if ((CUR != '<') || (NXT(1) != '!') ||
2667        (NXT(2) != '-') || (NXT(3) != '-')) return;
2668
2669    state = ctxt->instate;
2670    ctxt->instate = XML_PARSER_COMMENT;
2671    SHRINK;
2672    SKIP(4);
2673    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2674    if (buf == NULL) {
2675        fprintf(stderr, "malloc of %d byte failed\n", size);
2676        ctxt->instate = state;
2677        return;
2678    }
2679    q = CUR;
2680    NEXT;
2681    r = CUR;
2682    NEXT;
2683    cur = CUR;
2684    while (IS_CHAR(cur) &&
2685           ((cur != '>') ||
2686            (r != '-') || (q != '-'))) {
2687        if ((r == '-') && (q == '-')) {
2688            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2689                ctxt->sax->error(ctxt->userData,
2690               "Comment must not contain '--' (double-hyphen)`\n");
2691            ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
2692            ctxt->wellFormed = 0;
2693        }
2694        if (len + 1 >= size) {
2695            size *= 2;
2696            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2697            if (buf == NULL) {
2698                fprintf(stderr, "realloc of %d byte failed\n", size);
2699                ctxt->instate = state;
2700                return;
2701            }
2702        }
2703        buf[len++] = q;
2704        q = r;
2705        r = cur;
2706        NEXT;
2707        cur = CUR;
2708        if (cur == 0) {
2709            SHRINK;
2710            GROW;
2711            cur = CUR;
2712        }
2713    }
2714    buf[len] = 0;
2715    if (!IS_CHAR(cur)) {
2716        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2717            ctxt->sax->error(ctxt->userData,
2718                             "Comment not terminated \n<!--%.50s\n", buf);
2719        ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
2720        ctxt->wellFormed = 0;
2721    } else {
2722        NEXT;
2723        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
2724            ctxt->sax->comment(ctxt->userData, buf);
2725        xmlFree(buf);
2726    }
2727    ctxt->instate = state;
2728}
2729
2730/**
2731 * xmlOldParsePITarget:
2732 * @ctxt:  an XML parser context
2733 *
2734 * parse the name of a PI
2735 *
2736 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
2737 *
2738 * Returns the PITarget name or NULL
2739 */
2740
2741static xmlChar *
2742xmlOldParsePITarget(xmlParserCtxtPtr ctxt) {
2743    xmlChar *name;
2744
2745    name = xmlOldParseName(ctxt);
2746    if ((name != NULL) &&
2747        ((name[0] == 'x') || (name[0] == 'X')) &&
2748        ((name[1] == 'm') || (name[1] == 'M')) &&
2749        ((name[2] == 'l') || (name[2] == 'L'))) {
2750        int i;
2751        for (i = 0;;i++) {
2752            if (xmlW3CPIs[i] == NULL) break;
2753            if (!xmlStrcmp(name, (const xmlChar *)xmlW3CPIs[i]))
2754                return(name);
2755        }
2756        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
2757            ctxt->sax->warning(ctxt->userData,
2758                 "xmlParsePItarget: invalid name prefix 'xml'\n");
2759            ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
2760        }
2761    }
2762    return(name);
2763}
2764
2765/**
2766 * xmlOldParsePI:
2767 * @ctxt:  an XML parser context
2768 *
2769 * parse an XML Processing Instruction.
2770 *
2771 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
2772 *
2773 * The processing is transfered to SAX once parsed.
2774 */
2775
2776static void
2777xmlOldParsePI(xmlParserCtxtPtr ctxt) {
2778    xmlChar *buf = NULL;
2779    int len = 0;
2780    int size = XML_PARSER_BUFFER_SIZE;
2781    xmlChar cur;
2782    xmlChar *target;
2783    xmlParserInputState state;
2784
2785    if ((CUR == '<') && (NXT(1) == '?')) {
2786        state = ctxt->instate;
2787        ctxt->instate = XML_PARSER_PI;
2788        /*
2789         * this is a Processing Instruction.
2790         */
2791        SKIP(2);
2792        SHRINK;
2793
2794        /*
2795         * Parse the target name and check for special support like
2796         * namespace.
2797         */
2798        target = xmlOldParsePITarget(ctxt);
2799        if (target != NULL) {
2800            buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2801            if (buf == NULL) {
2802                fprintf(stderr, "malloc of %d byte failed\n", size);
2803                ctxt->instate = state;
2804                return;
2805            }
2806            cur = CUR;
2807            if (!IS_BLANK(cur)) {
2808                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2809                    ctxt->sax->error(ctxt->userData,
2810                      "xmlParsePI: PI %s space expected\n", target);
2811                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2812                ctxt->wellFormed = 0;
2813            }
2814            SKIP_BLANKS;
2815            cur = CUR;
2816            while (IS_CHAR(cur) &&
2817                   ((cur != '?') || (NXT(1) != '>'))) {
2818                if (len + 1 >= size) {
2819                    size *= 2;
2820                    buf = xmlRealloc(buf, size * sizeof(xmlChar));
2821                    if (buf == NULL) {
2822                        fprintf(stderr, "realloc of %d byte failed\n", size);
2823                        ctxt->instate = state;
2824                        return;
2825                    }
2826                }
2827                buf[len++] = cur;
2828                NEXT;
2829                cur = CUR;
2830                if (cur == 0) {
2831                    SHRINK;
2832                    GROW;
2833                    cur = CUR;
2834                }
2835            }
2836            buf[len] = 0;
2837            if (!IS_CHAR(cur)) {
2838                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2839                    ctxt->sax->error(ctxt->userData,
2840                      "xmlParsePI: PI %s never end ...\n", target);
2841                ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
2842                ctxt->wellFormed = 0;
2843            } else {
2844                SKIP(2);
2845
2846                /*
2847                 * SAX: PI detected.
2848                 */
2849                if ((ctxt->sax) &&
2850                    (ctxt->sax->processingInstruction != NULL))
2851                    ctxt->sax->processingInstruction(ctxt->userData,
2852                                                     target, buf);
2853            }
2854            xmlFree(buf);
2855            xmlFree(target);
2856        } else {
2857            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2858                ctxt->sax->error(ctxt->userData,
2859                       "xmlParsePI : no target name\n");
2860            ctxt->errNo = XML_ERR_PI_NOT_STARTED;
2861            ctxt->wellFormed = 0;
2862        }
2863        ctxt->instate = state;
2864    }
2865}
2866
2867/**
2868 * xmlOldParseNotationDecl:
2869 * @ctxt:  an XML parser context
2870 *
2871 * parse a notation declaration
2872 *
2873 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
2874 *
2875 * Hence there is actually 3 choices:
2876 *     'PUBLIC' S PubidLiteral
2877 *     'PUBLIC' S PubidLiteral S SystemLiteral
2878 * and 'SYSTEM' S SystemLiteral
2879 *
2880 * See the NOTE on xmlOldParseExternalID().
2881 */
2882
2883static void
2884xmlOldParseNotationDecl(xmlParserCtxtPtr ctxt) {
2885    xmlChar *name;
2886    xmlChar *Pubid;
2887    xmlChar *Systemid;
2888   
2889    if ((CUR == '<') && (NXT(1) == '!') &&
2890        (NXT(2) == 'N') && (NXT(3) == 'O') &&
2891        (NXT(4) == 'T') && (NXT(5) == 'A') &&
2892        (NXT(6) == 'T') && (NXT(7) == 'I') &&
2893        (NXT(8) == 'O') && (NXT(9) == 'N')) {
2894        SHRINK;
2895        SKIP(10);
2896        if (!IS_BLANK(CUR)) {
2897            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2898                ctxt->sax->error(ctxt->userData,
2899                                 "Space required after '<!NOTATION'\n");
2900            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2901            ctxt->wellFormed = 0;
2902            return;
2903        }
2904        SKIP_BLANKS;
2905
2906        name = xmlOldParseName(ctxt);
2907        if (name == NULL) {
2908            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2909                ctxt->sax->error(ctxt->userData,
2910                                 "NOTATION: Name expected here\n");
2911            ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
2912            ctxt->wellFormed = 0;
2913            return;
2914        }
2915        if (!IS_BLANK(CUR)) {
2916            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2917                ctxt->sax->error(ctxt->userData,
2918                     "Space required after the NOTATION name'\n");
2919            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2920            ctxt->wellFormed = 0;
2921            return;
2922        }
2923        SKIP_BLANKS;
2924
2925        /*
2926         * Parse the IDs.
2927         */
2928        Systemid = xmlOldParseExternalID(ctxt, &Pubid, 1);
2929        SKIP_BLANKS;
2930
2931        if (CUR == '>') {
2932            NEXT;
2933            if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
2934                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
2935        } else {
2936            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2937                ctxt->sax->error(ctxt->userData,
2938                       "'>' required to close NOTATION declaration\n");
2939            ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
2940            ctxt->wellFormed = 0;
2941        }
2942        xmlFree(name);
2943        if (Systemid != NULL) xmlFree(Systemid);
2944        if (Pubid != NULL) xmlFree(Pubid);
2945    }
2946}
2947
2948/**
2949 * xmlOldParseEntityDecl:
2950 * @ctxt:  an XML parser context
2951 *
2952 * parse <!ENTITY declarations
2953 *
2954 * [70] EntityDecl ::= GEDecl | PEDecl
2955 *
2956 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
2957 *
2958 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
2959 *
2960 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
2961 *
2962 * [74] PEDef ::= EntityValue | ExternalID
2963 *
2964 * [76] NDataDecl ::= S 'NDATA' S Name
2965 *
2966 * [ VC: Notation Declared ]
2967 * The Name must match the declared name of a notation.
2968 */
2969
2970static void
2971xmlOldParseEntityDecl(xmlParserCtxtPtr ctxt) {
2972    xmlChar *name = NULL;
2973    xmlChar *value = NULL;
2974    xmlChar *URI = NULL, *literal = NULL;
2975    xmlChar *ndata = NULL;
2976    int isParameter = 0;
2977    xmlChar *orig = NULL;
2978   
2979    GROW;
2980    if ((CUR == '<') && (NXT(1) == '!') &&
2981        (NXT(2) == 'E') && (NXT(3) == 'N') &&
2982        (NXT(4) == 'T') && (NXT(5) == 'I') &&
2983        (NXT(6) == 'T') && (NXT(7) == 'Y')) {
2984        ctxt->instate = XML_PARSER_ENTITY_DECL;
2985        SHRINK;
2986        SKIP(8);
2987        if (!IS_BLANK(CUR)) {
2988            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2989                ctxt->sax->error(ctxt->userData,
2990                                 "Space required after '<!ENTITY'\n");
2991            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2992            ctxt->wellFormed = 0;
2993        }
2994        SKIP_BLANKS;
2995
2996        if (CUR == '%') {
2997            NEXT;
2998            if (!IS_BLANK(CUR)) {
2999                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3000                    ctxt->sax->error(ctxt->userData,
3001                                     "Space required after '%'\n");
3002                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3003                ctxt->wellFormed = 0;
3004            }
3005            SKIP_BLANKS;
3006            isParameter = 1;
3007        }
3008
3009        name = xmlOldParseName(ctxt);
3010        if (name == NULL) {
3011            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3012                ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
3013            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3014            ctxt->wellFormed = 0;
3015            return;
3016        }
3017        if (!IS_BLANK(CUR)) {
3018            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3019                ctxt->sax->error(ctxt->userData,
3020                     "Space required after the entity name\n");
3021            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3022            ctxt->wellFormed = 0;
3023        }
3024        SKIP_BLANKS;
3025
3026        /*
3027         * handle the various case of definitions...
3028         */
3029        if (isParameter) {
3030            if ((CUR == '"') || (CUR == '\''))
3031                value = xmlOldParseEntityValue(ctxt, &orig);
3032                if (value) {
3033                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3034                        ctxt->sax->entityDecl(ctxt->userData, name,
3035                                    XML_INTERNAL_PARAMETER_ENTITY,
3036                                    NULL, NULL, value);
3037                }
3038            else {
3039                URI = xmlOldParseExternalID(ctxt, &literal, 1);
3040                if (URI) {
3041                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3042                        ctxt->sax->entityDecl(ctxt->userData, name,
3043                                    XML_EXTERNAL_PARAMETER_ENTITY,
3044                                    literal, URI, NULL);
3045                }
3046            }
3047        } else {
3048            if ((CUR == '"') || (CUR == '\'')) {
3049                value = xmlOldParseEntityValue(ctxt, &orig);
3050                if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3051                    ctxt->sax->entityDecl(ctxt->userData, name,
3052                                XML_INTERNAL_GENERAL_ENTITY,
3053                                NULL, NULL, value);
3054            } else {
3055                URI = xmlOldParseExternalID(ctxt, &literal, 1);
3056                if ((CUR != '>') && (!IS_BLANK(CUR))) {
3057                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3058                        ctxt->sax->error(ctxt->userData,
3059                            "Space required before 'NDATA'\n");
3060                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3061                    ctxt->wellFormed = 0;
3062                }
3063                SKIP_BLANKS;
3064                if ((CUR == 'N') && (NXT(1) == 'D') &&
3065                    (NXT(2) == 'A') && (NXT(3) == 'T') &&
3066                    (NXT(4) == 'A')) {
3067                    SKIP(5);
3068                    if (!IS_BLANK(CUR)) {
3069                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3070                            ctxt->sax->error(ctxt->userData,
3071                                "Space required after 'NDATA'\n");
3072                        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3073                        ctxt->wellFormed = 0;
3074                    }
3075                    SKIP_BLANKS;
3076                    ndata = xmlOldParseName(ctxt);
3077                    if ((ctxt->sax != NULL) &&
3078                        (ctxt->sax->unparsedEntityDecl != NULL))
3079                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
3080                                    literal, URI, ndata);
3081                } else {
3082                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3083                        ctxt->sax->entityDecl(ctxt->userData, name,
3084                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
3085                                    literal, URI, NULL);
3086                }
3087            }
3088        }
3089        SKIP_BLANKS;
3090        if (CUR != '>') {
3091            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3092                ctxt->sax->error(ctxt->userData,
3093                    "xmlParseEntityDecl: entity %s not terminated\n", name);
3094            ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
3095            ctxt->wellFormed = 0;
3096        } else
3097            NEXT;
3098        if (orig != NULL) {
3099            /*
3100             * Ugly mechanism to save the raw entity value.
3101             */
3102            xmlEntityPtr cur = NULL;
3103
3104            if (isParameter) {
3105                if ((ctxt->sax != NULL) &&
3106                    (ctxt->sax->getParameterEntity != NULL))
3107                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
3108            } else {
3109                if ((ctxt->sax != NULL) &&
3110                    (ctxt->sax->getEntity != NULL))
3111                    cur = ctxt->sax->getEntity(ctxt->userData, name);
3112            }
3113            if (cur != NULL) {
3114                if (cur->orig != NULL)
3115                    xmlFree(orig);
3116                else
3117                    cur->orig = orig;
3118            } else
3119                xmlFree(orig);
3120        }
3121        if (name != NULL) xmlFree(name);
3122        if (value != NULL) xmlFree(value);
3123        if (URI != NULL) xmlFree(URI);
3124        if (literal != NULL) xmlFree(literal);
3125        if (ndata != NULL) xmlFree(ndata);
3126    }
3127}
3128
3129/**
3130 * xmlOldParseDefaultDecl:
3131 * @ctxt:  an XML parser context
3132 * @value:  Receive a possible fixed default value for the attribute
3133 *
3134 * Parse an attribute default declaration
3135 *
3136 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
3137 *
3138 * [ VC: Required Attribute ]
3139 * if the default declaration is the keyword #REQUIRED, then the
3140 * attribute must be specified for all elements of the type in the
3141 * attribute-list declaration.
3142 *
3143 * [ VC: Attribute Default Legal ]
3144 * The declared default value must meet the lexical constraints of
3145 * the declared attribute type c.f. xmlValidateAttributeDecl()
3146 *
3147 * [ VC: Fixed Attribute Default ]
3148 * if an attribute has a default value declared with the #FIXED
3149 * keyword, instances of that attribute must match the default value.
3150 *
3151 * [ WFC: No < in Attribute Values ]
3152 * handled in xmlOldParseAttValue()
3153 *
3154 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
3155 *          or XML_ATTRIBUTE_FIXED.
3156 */
3157
3158static int
3159xmlOldParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
3160    int val;
3161    xmlChar *ret;
3162
3163    *value = NULL;
3164    if ((CUR == '#') && (NXT(1) == 'R') &&
3165        (NXT(2) == 'E') && (NXT(3) == 'Q') &&
3166        (NXT(4) == 'U') && (NXT(5) == 'I') &&
3167        (NXT(6) == 'R') && (NXT(7) == 'E') &&
3168        (NXT(8) == 'D')) {
3169        SKIP(9);
3170        return(XML_ATTRIBUTE_REQUIRED);
3171    }
3172    if ((CUR == '#') && (NXT(1) == 'I') &&
3173        (NXT(2) == 'M') && (NXT(3) == 'P') &&
3174        (NXT(4) == 'L') && (NXT(5) == 'I') &&
3175        (NXT(6) == 'E') && (NXT(7) == 'D')) {
3176        SKIP(8);
3177        return(XML_ATTRIBUTE_IMPLIED);
3178    }
3179    val = XML_ATTRIBUTE_NONE;
3180    if ((CUR == '#') && (NXT(1) == 'F') &&
3181        (NXT(2) == 'I') && (NXT(3) == 'X') &&
3182        (NXT(4) == 'E') && (NXT(5) == 'D')) {
3183        SKIP(6);
3184        val = XML_ATTRIBUTE_FIXED;
3185        if (!IS_BLANK(CUR)) {
3186            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3187                ctxt->sax->error(ctxt->userData,
3188                                 "Space required after '#FIXED'\n");
3189            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3190            ctxt->wellFormed = 0;
3191        }
3192        SKIP_BLANKS;
3193    }
3194    ret = xmlOldParseAttValue(ctxt);
3195    ctxt->instate = XML_PARSER_DTD;
3196    if (ret == NULL) {
3197        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3198            ctxt->sax->error(ctxt->userData,
3199               "Attribute default value declaration error\n");
3200        ctxt->wellFormed = 0;
3201    } else
3202        *value = ret;
3203    return(val);
3204}
3205
3206/**
3207 * xmlOldParseNotationType:
3208 * @ctxt:  an XML parser context
3209 *
3210 * parse an Notation attribute type.
3211 *
3212 * Note: the leading 'NOTATION' S part has already being parsed...
3213 *
3214 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3215 *
3216 * [ VC: Notation Attributes ]
3217 * Values of this type must match one of the notation names included
3218 * in the declaration; all notation names in the declaration must be declared.
3219 *
3220 * Returns: the notation attribute tree built while parsing
3221 */
3222
3223static xmlEnumerationPtr
3224xmlOldParseNotationType(xmlParserCtxtPtr ctxt) {
3225    xmlChar *name;
3226    xmlEnumerationPtr ret = NULL, last = NULL, cur;
3227
3228    if (CUR != '(') {
3229        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3230            ctxt->sax->error(ctxt->userData,
3231                             "'(' required to start 'NOTATION'\n");
3232        ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
3233        ctxt->wellFormed = 0;
3234        return(NULL);
3235    }
3236    SHRINK;
3237    do {
3238        NEXT;
3239        SKIP_BLANKS;
3240        name = xmlOldParseName(ctxt);
3241        if (name == NULL) {
3242            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3243                ctxt->sax->error(ctxt->userData,
3244                                 "Name expected in NOTATION declaration\n");
3245            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3246            ctxt->wellFormed = 0;
3247            return(ret);
3248        }
3249        cur = xmlCreateEnumeration(name);
3250        xmlFree(name);
3251        if (cur == NULL) return(ret);
3252        if (last == NULL) ret = last = cur;
3253        else {
3254            last->next = cur;
3255            last = cur;
3256        }
3257        SKIP_BLANKS;
3258    } while (CUR == '|');
3259    if (CUR != ')') {
3260        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3261            ctxt->sax->error(ctxt->userData,
3262                             "')' required to finish NOTATION declaration\n");
3263        ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
3264        ctxt->wellFormed = 0;
3265        return(ret);
3266    }
3267    NEXT;
3268    return(ret);
3269}
3270
3271/**
3272 * xmlOldParseEnumerationType:
3273 * @ctxt:  an XML parser context
3274 *
3275 * parse an Enumeration attribute type.
3276 *
3277 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
3278 *
3279 * [ VC: Enumeration ]
3280 * Values of this type must match one of the Nmtoken tokens in
3281 * the declaration
3282 *
3283 * Returns: the enumeration attribute tree built while parsing
3284 */
3285
3286static xmlEnumerationPtr
3287xmlOldParseEnumerationType(xmlParserCtxtPtr ctxt) {
3288    xmlChar *name;
3289    xmlEnumerationPtr ret = NULL, last = NULL, cur;
3290
3291    if (CUR != '(') {
3292        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3293            ctxt->sax->error(ctxt->userData,
3294                             "'(' required to start ATTLIST enumeration\n");
3295        ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
3296        ctxt->wellFormed = 0;
3297        return(NULL);
3298    }
3299    SHRINK;
3300    do {
3301        NEXT;
3302        SKIP_BLANKS;
3303        name = xmlOldParseNmtoken(ctxt);
3304        if (name == NULL) {
3305            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3306                ctxt->sax->error(ctxt->userData,
3307                                 "NmToken expected in ATTLIST enumeration\n");
3308            ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
3309            ctxt->wellFormed = 0;
3310            return(ret);
3311        }
3312        cur = xmlCreateEnumeration(name);
3313        xmlFree(name);
3314        if (cur == NULL) return(ret);
3315        if (last == NULL) ret = last = cur;
3316        else {
3317            last->next = cur;
3318            last = cur;
3319        }
3320        SKIP_BLANKS;
3321    } while (CUR == '|');
3322    if (CUR != ')') {
3323        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3324            ctxt->sax->error(ctxt->userData,
3325                             "')' required to finish ATTLIST enumeration\n");
3326        ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
3327        ctxt->wellFormed = 0;
3328        return(ret);
3329    }
3330    NEXT;
3331    return(ret);
3332}
3333
3334/**
3335 * xmlOldParseEnumeratedType:
3336 * @ctxt:  an XML parser context
3337 * @tree:  the enumeration tree built while parsing
3338 *
3339 * parse an Enumerated attribute type.
3340 *
3341 * [57] EnumeratedType ::= NotationType | Enumeration
3342 *
3343 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3344 *
3345 *
3346 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
3347 */
3348
3349static int
3350xmlOldParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3351    if ((CUR == 'N') && (NXT(1) == 'O') &&
3352        (NXT(2) == 'T') && (NXT(3) == 'A') &&
3353        (NXT(4) == 'T') && (NXT(5) == 'I') &&
3354        (NXT(6) == 'O') && (NXT(7) == 'N')) {
3355        SKIP(8);
3356        if (!IS_BLANK(CUR)) {
3357            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3358                ctxt->sax->error(ctxt->userData,
3359                                 "Space required after 'NOTATION'\n");
3360            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3361            ctxt->wellFormed = 0;
3362            return(0);
3363        }
3364        SKIP_BLANKS;
3365        *tree = xmlOldParseNotationType(ctxt);
3366        if (*tree == NULL) return(0);
3367        return(XML_ATTRIBUTE_NOTATION);
3368    }
3369    *tree = xmlOldParseEnumerationType(ctxt);
3370    if (*tree == NULL) return(0);
3371    return(XML_ATTRIBUTE_ENUMERATION);
3372}
3373
3374/**
3375 * xmlOldParseAttributeType:
3376 * @ctxt:  an XML parser context
3377 * @tree:  the enumeration tree built while parsing
3378 *
3379 * parse the Attribute list def for an element
3380 *
3381 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
3382 *
3383 * [55] StringType ::= 'CDATA'
3384 *
3385 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
3386 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
3387 *
3388 * Validity constraints for attribute values syntax are checked in
3389 * xmlValidateAttributeValue()
3390 *
3391 * [ VC: ID ]
3392 * Values of type ID must match the Name production. A name must not
3393 * appear more than once in an XML document as a value of this type;
3394 * i.e., ID values must uniquely identify the elements which bear them.
3395 *
3396 * [ VC: One ID per Element Type ]
3397 * No element type may have more than one ID attribute specified.
3398 *
3399 * [ VC: ID Attribute Default ]
3400 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
3401 *
3402 * [ VC: IDREF ]
3403 * Values of type IDREF must match the Name production, and values
3404 * of type IDREFS must match Names; each IDREF Name must match the value
3405 * of an ID attribute on some element in the XML document; i.e. IDREF
3406 * values must match the value of some ID attribute.
3407 *
3408 * [ VC: Entity Name ]
3409 * Values of type ENTITY must match the Name production, values
3410 * of type ENTITIES must match Names; each Entity Name must match the
3411 * name of an unparsed entity declared in the DTD. 
3412 *
3413 * [ VC: Name Token ]
3414 * Values of type NMTOKEN must match the Nmtoken production; values
3415 * of type NMTOKENS must match Nmtokens.
3416 *
3417 * Returns the attribute type
3418 */
3419static int
3420xmlOldParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3421    SHRINK;
3422    if ((CUR == 'C') && (NXT(1) == 'D') &&
3423        (NXT(2) == 'A') && (NXT(3) == 'T') &&
3424        (NXT(4) == 'A')) {
3425        SKIP(5);
3426        return(XML_ATTRIBUTE_CDATA);
3427     } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3428        (NXT(2) == 'R') && (NXT(3) == 'E') &&
3429        (NXT(4) == 'F') && (NXT(5) == 'S')) {
3430        SKIP(6);
3431        return(XML_ATTRIBUTE_IDREFS);
3432     } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3433        (NXT(2) == 'R') && (NXT(3) == 'E') &&
3434        (NXT(4) == 'F')) {
3435        SKIP(5);
3436        return(XML_ATTRIBUTE_IDREF);
3437     } else if ((CUR == 'I') && (NXT(1) == 'D')) {
3438        SKIP(2);
3439        return(XML_ATTRIBUTE_ID);
3440     } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3441        (NXT(2) == 'T') && (NXT(3) == 'I') &&
3442        (NXT(4) == 'T') && (NXT(5) == 'Y')) {
3443        SKIP(6);
3444        return(XML_ATTRIBUTE_ENTITY);
3445     } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3446        (NXT(2) == 'T') && (NXT(3) == 'I') &&
3447        (NXT(4) == 'T') && (NXT(5) == 'I') &&
3448        (NXT(6) == 'E') && (NXT(7) == 'S')) {
3449        SKIP(8);
3450        return(XML_ATTRIBUTE_ENTITIES);
3451     } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3452        (NXT(2) == 'T') && (NXT(3) == 'O') &&
3453        (NXT(4) == 'K') && (NXT(5) == 'E') &&
3454        (NXT(6) == 'N') && (NXT(7) == 'S')) {
3455        SKIP(8);
3456        return(XML_ATTRIBUTE_NMTOKENS);
3457     } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3458        (NXT(2) == 'T') && (NXT(3) == 'O') &&
3459        (NXT(4) == 'K') && (NXT(5) == 'E') &&
3460        (NXT(6) == 'N')) {
3461        SKIP(7);
3462        return(XML_ATTRIBUTE_NMTOKEN);
3463     }
3464     return(xmlOldParseEnumeratedType(ctxt, tree));
3465}
3466
3467/**
3468 * xmlOldParseAttributeListDecl:
3469 * @ctxt:  an XML parser context
3470 *
3471 * : parse the Attribute list def for an element
3472 *
3473 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
3474 *
3475 * [53] AttDef ::= S Name S AttType S DefaultDecl
3476 *
3477 */
3478static void
3479xmlOldParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
3480    xmlChar *elemName;
3481    xmlChar *attrName;
3482    xmlEnumerationPtr tree;
3483
3484    if ((CUR == '<') && (NXT(1) == '!') &&
3485        (NXT(2) == 'A') && (NXT(3) == 'T') &&
3486        (NXT(4) == 'T') && (NXT(5) == 'L') &&
3487        (NXT(6) == 'I') && (NXT(7) == 'S') &&
3488        (NXT(8) == 'T')) {
3489        SKIP(9);
3490        if (!IS_BLANK(CUR)) {
3491            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3492                ctxt->sax->error(ctxt->userData,
3493                                 "Space required after '<!ATTLIST'\n");
3494            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3495            ctxt->wellFormed = 0;
3496        }
3497        SKIP_BLANKS;
3498        elemName = xmlOldParseName(ctxt);
3499        if (elemName == NULL) {
3500            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3501                ctxt->sax->error(ctxt->userData,
3502                                 "ATTLIST: no name for Element\n");
3503            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3504            ctxt->wellFormed = 0;
3505            return;
3506        }
3507        SKIP_BLANKS;
3508        while (CUR != '>') {
3509            const xmlChar *check = CUR_PTR;
3510            int type;
3511            int def;
3512            xmlChar *defaultValue = NULL;
3513
3514            tree = NULL;
3515            attrName = xmlOldParseName(ctxt);
3516            if (attrName == NULL) {
3517                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3518                    ctxt->sax->error(ctxt->userData,
3519                                     "ATTLIST: no name for Attribute\n");
3520                ctxt->errNo = XML_ERR_NAME_REQUIRED;
3521                ctxt->wellFormed = 0;
3522                break;
3523            }
3524            GROW;
3525            if (!IS_BLANK(CUR)) {
3526                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3527                    ctxt->sax->error(ctxt->userData,
3528                        "Space required after the attribute name\n");
3529                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3530                ctxt->wellFormed = 0;
3531                break;
3532            }
3533            SKIP_BLANKS;
3534
3535            type = xmlOldParseAttributeType(ctxt, &tree);
3536            if (type <= 0) break;
3537
3538            GROW;
3539            if (!IS_BLANK(CUR)) {
3540                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3541                    ctxt->sax->error(ctxt->userData,
3542                        "Space required after the attribute type\n");
3543                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3544                ctxt->wellFormed = 0;
3545                break;
3546            }
3547            SKIP_BLANKS;
3548
3549            def = xmlOldParseDefaultDecl(ctxt, &defaultValue);
3550            if (def <= 0) break;
3551
3552            GROW;
3553            if (CUR != '>') {
3554                if (!IS_BLANK(CUR)) {
3555                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3556                        ctxt->sax->error(ctxt->userData,
3557                        "Space required after the attribute default value\n");
3558                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3559                    ctxt->wellFormed = 0;
3560                    break;
3561                }
3562                SKIP_BLANKS;
3563            }
3564            if (check == CUR_PTR) {
3565                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3566                    ctxt->sax->error(ctxt->userData,
3567                    "xmlParseAttributeListDecl: detected internal error\n");
3568                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
3569                break;
3570            }
3571            if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
3572                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
3573                                type, def, defaultValue, tree);
3574            if (attrName != NULL)
3575                xmlFree(attrName);
3576            if (defaultValue != NULL)
3577                xmlFree(defaultValue);
3578            GROW;
3579        }
3580        if (CUR == '>')
3581            NEXT;
3582
3583        xmlFree(elemName);
3584    }
3585}
3586
3587/**
3588 * xmlOldParseElementMixedContentDecl:
3589 * @ctxt:  an XML parser context
3590 *
3591 * parse the declaration for a Mixed Element content
3592 * The leading '(' and spaces have been skipped in xmlOldParseElementContentDecl
3593 *
3594 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
3595 *                '(' S? '#PCDATA' S? ')'
3596 *
3597 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
3598 *
3599 * [ VC: No Duplicate Types ]
3600 * The same name must not appear more than once in a single
3601 * mixed-content declaration.
3602 *
3603 * returns: the list of the xmlElementContentPtr describing the element choices
3604 */
3605static xmlElementContentPtr
3606xmlOldParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
3607    xmlElementContentPtr ret = NULL, cur = NULL, n;
3608    xmlChar *elem = NULL;
3609
3610    GROW;
3611    if ((CUR == '#') && (NXT(1) == 'P') &&
3612        (NXT(2) == 'C') && (NXT(3) == 'D') &&
3613        (NXT(4) == 'A') && (NXT(5) == 'T') &&
3614        (NXT(6) == 'A')) {
3615        SKIP(7);
3616        SKIP_BLANKS;
3617        SHRINK;
3618        if (CUR == ')') {
3619            NEXT;
3620            ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3621            if (CUR == '*') {
3622                ret->ocur = XML_ELEMENT_CONTENT_MULT;
3623                NEXT;
3624            }
3625            return(ret);
3626        }
3627        if ((CUR == '(') || (CUR == '|')) {
3628            ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3629            if (ret == NULL) return(NULL);
3630        }
3631        while (CUR == '|') {
3632            NEXT;
3633            if (elem == NULL) {
3634                ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3635                if (ret == NULL) return(NULL);
3636                ret->c1 = cur;
3637                cur = ret;
3638            } else {
3639                n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3640                if (n == NULL) return(NULL);
3641                n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3642                cur->c2 = n;
3643                cur = n;
3644                xmlFree(elem);
3645            }
3646            SKIP_BLANKS;
3647            elem = xmlOldParseName(ctxt);
3648            if (elem == NULL) {
3649                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3650                    ctxt->sax->error(ctxt->userData,
3651                        "xmlParseElementMixedContentDecl : Name expected\n");
3652                ctxt->errNo = XML_ERR_NAME_REQUIRED;
3653                ctxt->wellFormed = 0;
3654                xmlFreeElementContent(cur);
3655                return(NULL);
3656            }
3657            SKIP_BLANKS;
3658            GROW;
3659        }
3660        if ((CUR == ')') && (NXT(1) == '*')) {
3661            if (elem != NULL) {
3662                cur->c2 = xmlNewElementContent(elem,
3663                                               XML_ELEMENT_CONTENT_ELEMENT);
3664                xmlFree(elem);
3665            }
3666            ret->ocur = XML_ELEMENT_CONTENT_MULT;
3667            SKIP(2);
3668        } else {
3669            if (elem != NULL) xmlFree(elem);
3670            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3671                ctxt->sax->error(ctxt->userData,
3672                    "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
3673            ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
3674            ctxt->wellFormed = 0;
3675            xmlFreeElementContent(ret);
3676            return(NULL);
3677        }
3678
3679    } else {
3680        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3681            ctxt->sax->error(ctxt->userData,
3682                "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
3683        ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
3684        ctxt->wellFormed = 0;
3685    }
3686    return(ret);
3687}
3688
3689/**
3690 * xmlOldParseElementChildrenContentDecl:
3691 * @ctxt:  an XML parser context
3692 *
3693 * parse the declaration for a Mixed Element content
3694 * The leading '(' and spaces have been skipped in xmlOldParseElementContentDecl
3695 *
3696 *
3697 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
3698 *
3699 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
3700 *
3701 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
3702 *
3703 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
3704 *
3705 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
3706 * TODO Parameter-entity replacement text must be properly nested
3707 *      with parenthetized groups. That is to say, if either of the
3708 *      opening or closing parentheses in a choice, seq, or Mixed
3709 *      construct is contained in the replacement text for a parameter
3710 *      entity, both must be contained in the same replacement text. For
3711 *      interoperability, if a parameter-entity reference appears in a
3712 *      choice, seq, or Mixed construct, its replacement text should not
3713 *      be empty, and neither the first nor last non-blank character of
3714 *      the replacement text should be a connector (| or ,).
3715 *
3716 * returns: the tree of xmlElementContentPtr describing the element
3717 *          hierarchy.
3718 */
3719static xmlElementContentPtr
3720xmlOldParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
3721    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
3722    xmlChar *elem;
3723    xmlChar type = 0;
3724
3725    SKIP_BLANKS;
3726    GROW;
3727    if (CUR == '(') {
3728        /* Recurse on first child */
3729        NEXT;
3730        SKIP_BLANKS;
3731        cur = ret = xmlOldParseElementChildrenContentDecl(ctxt);
3732        SKIP_BLANKS;
3733        GROW;
3734    } else {
3735        elem = xmlOldParseName(ctxt);
3736        if (elem == NULL) {
3737            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3738                ctxt->sax->error(ctxt->userData,
3739                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
3740            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3741            ctxt->wellFormed = 0;
3742            return(NULL);
3743        }
3744        cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3745        GROW;
3746        if (CUR == '?') {
3747            cur->ocur = XML_ELEMENT_CONTENT_OPT;
3748            NEXT;
3749        } else if (CUR == '*') {
3750            cur->ocur = XML_ELEMENT_CONTENT_MULT;
3751            NEXT;
3752        } else if (CUR == '+') {
3753            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
3754            NEXT;
3755        } else {
3756            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
3757        }
3758        xmlFree(elem);
3759        GROW;
3760    }
3761    SKIP_BLANKS;
3762    SHRINK;
3763    while (CUR != ')') {
3764        /*
3765         * Each loop we parse one separator and one element.
3766         */
3767        if (CUR == ',') {
3768            if (type == 0) type = CUR;
3769
3770            /*
3771             * Detect "Name | Name , Name" error
3772             */
3773            else if (type != CUR) {
3774                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3775                    ctxt->sax->error(ctxt->userData,
3776                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
3777                    type);
3778                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
3779                ctxt->wellFormed = 0;
3780                xmlFreeElementContent(ret);
3781                return(NULL);
3782            }
3783            NEXT;
3784
3785            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
3786            if (op == NULL) {
3787                xmlFreeElementContent(ret);
3788                return(NULL);
3789            }
3790            if (last == NULL) {
3791                op->c1 = ret;
3792                ret = cur = op;
3793            } else {
3794                cur->c2 = op;
3795                op->c1 = last;
3796                cur =op;
3797                last = NULL;
3798            }
3799        } else if (CUR == '|') {
3800            if (type == 0) type = CUR;
3801
3802            /*
3803             * Detect "Name , Name | Name" error
3804             */
3805            else if (type != CUR) {
3806                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3807                    ctxt->sax->error(ctxt->userData,
3808                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
3809                    type);
3810                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
3811                ctxt->wellFormed = 0;
3812                xmlFreeElementContent(ret);
3813                return(NULL);
3814            }
3815            NEXT;
3816
3817            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3818            if (op == NULL) {
3819                xmlFreeElementContent(ret);
3820                return(NULL);
3821            }
3822            if (last == NULL) {
3823                op->c1 = ret;
3824                ret = cur = op;
3825            } else {
3826                cur->c2 = op;
3827                op->c1 = last;
3828                cur =op;
3829                last = NULL;
3830            }
3831        } else {
3832            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3833                ctxt->sax->error(ctxt->userData,
3834            "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
3835            ctxt->wellFormed = 0;
3836            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
3837            xmlFreeElementContent(ret);
3838            return(NULL);
3839        }
3840        GROW;
3841        SKIP_BLANKS;
3842        GROW;
3843        if (CUR == '(') {
3844            /* Recurse on second child */
3845            NEXT;
3846            SKIP_BLANKS;
3847            last = xmlOldParseElementChildrenContentDecl(ctxt);
3848            SKIP_BLANKS;
3849        } else {
3850            elem = xmlOldParseName(ctxt);
3851            if (elem == NULL) {
3852                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3853                    ctxt->sax->error(ctxt->userData,
3854                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
3855                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3856                ctxt->wellFormed = 0;
3857                return(NULL);
3858            }
3859            last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3860            xmlFree(elem);
3861            if (CUR == '?') {
3862                last->ocur = XML_ELEMENT_CONTENT_OPT;
3863                NEXT;
3864            } else if (CUR == '*') {
3865                last->ocur = XML_ELEMENT_CONTENT_MULT;
3866                NEXT;
3867            } else if (CUR == '+') {
3868                last->ocur = XML_ELEMENT_CONTENT_PLUS;
3869                NEXT;
3870            } else {
3871                last->ocur = XML_ELEMENT_CONTENT_ONCE;
3872            }
3873        }
3874        SKIP_BLANKS;
3875        GROW;
3876    }
3877    if ((cur != NULL) && (last != NULL)) {
3878        cur->c2 = last;
3879    }
3880    NEXT;
3881    if (CUR == '?') {
3882        ret->ocur = XML_ELEMENT_CONTENT_OPT;
3883        NEXT;
3884    } else if (CUR == '*') {
3885        ret->ocur = XML_ELEMENT_CONTENT_MULT;
3886        NEXT;
3887    } else if (CUR == '+') {
3888        ret->ocur = XML_ELEMENT_CONTENT_PLUS;
3889        NEXT;
3890    }
3891    return(ret);
3892}
3893
3894/**
3895 * xmlOldParseElementContentDecl:
3896 * @ctxt:  an XML parser context
3897 * @name:  the name of the element being defined.
3898 * @result:  the Element Content pointer will be stored here if any
3899 *
3900 * parse the declaration for an Element content either Mixed or Children,
3901 * the cases EMPTY and ANY are handled directly in xmlOldParseElementDecl
3902 *
3903 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
3904 *
3905 * returns: the type of element content XML_ELEMENT_TYPE_xxx
3906 */
3907
3908static int
3909xmlOldParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
3910                           xmlElementContentPtr *result) {
3911
3912    xmlElementContentPtr tree = NULL;
3913    int res;
3914
3915    *result = NULL;
3916
3917    if (CUR != '(') {
3918        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3919            ctxt->sax->error(ctxt->userData,
3920                "xmlParseElementContentDecl : '(' expected\n");
3921        ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3922        ctxt->wellFormed = 0;
3923        return(-1);
3924    }
3925    NEXT;
3926    GROW;
3927    SKIP_BLANKS;
3928    if ((CUR == '#') && (NXT(1) == 'P') &&
3929        (NXT(2) == 'C') && (NXT(3) == 'D') &&
3930        (NXT(4) == 'A') && (NXT(5) == 'T') &&
3931        (NXT(6) == 'A')) {
3932        tree = xmlOldParseElementMixedContentDecl(ctxt);
3933        res = XML_ELEMENT_TYPE_MIXED;
3934    } else {
3935        tree = xmlOldParseElementChildrenContentDecl(ctxt);
3936        res = XML_ELEMENT_TYPE_ELEMENT;
3937    }
3938    SKIP_BLANKS;
3939    /****************************
3940    if (CUR != ')') {
3941        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3942            ctxt->sax->error(ctxt->userData,
3943                "xmlParseElementContentDecl : ')' expected\n");
3944        ctxt->wellFormed = 0;
3945        return(-1);
3946    }
3947     ****************************/
3948    *result = tree;
3949    return(res);
3950}
3951
3952/**
3953 * xmlOldParseElementDecl:
3954 * @ctxt:  an XML parser context
3955 *
3956 * parse an Element declaration.
3957 *
3958 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
3959 *
3960 * [ VC: Unique Element Type Declaration ]
3961 * No element type may be declared more than once
3962 *
3963 * Returns the type of the element, or -1 in case of error
3964 */
3965static int
3966xmlOldParseElementDecl(xmlParserCtxtPtr ctxt) {
3967    xmlChar *name;
3968    int ret = -1;
3969    xmlElementContentPtr content  = NULL;
3970
3971    GROW;
3972    if ((CUR == '<') && (NXT(1) == '!') &&
3973        (NXT(2) == 'E') && (NXT(3) == 'L') &&
3974        (NXT(4) == 'E') && (NXT(5) == 'M') &&
3975        (NXT(6) == 'E') && (NXT(7) == 'N') &&
3976        (NXT(8) == 'T')) {
3977        SKIP(9);
3978        if (!IS_BLANK(CUR)) {
3979            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3980                ctxt->sax->error(ctxt->userData,
3981                    "Space required after 'ELEMENT'\n");
3982            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3983            ctxt->wellFormed = 0;
3984        }
3985        SKIP_BLANKS;
3986        name = xmlOldParseName(ctxt);
3987        if (name == NULL) {
3988            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3989                ctxt->sax->error(ctxt->userData,
3990                   "xmlParseElementDecl: no name for Element\n");
3991            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3992            ctxt->wellFormed = 0;
3993            return(-1);
3994        }
3995        if (!IS_BLANK(CUR)) {
3996            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3997                ctxt->sax->error(ctxt->userData,
3998                    "Space required after the element name\n");
3999            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4000            ctxt->wellFormed = 0;
4001        }
4002        SKIP_BLANKS;
4003        if ((CUR == 'E') && (NXT(1) == 'M') &&
4004            (NXT(2) == 'P') && (NXT(3) == 'T') &&
4005            (NXT(4) == 'Y')) {
4006            SKIP(5);
4007            /*
4008             * Element must always be empty.
4009             */
4010            ret = XML_ELEMENT_TYPE_EMPTY;
4011        } else if ((CUR == 'A') && (NXT(1) == 'N') &&
4012                   (NXT(2) == 'Y')) {
4013            SKIP(3);
4014            /*
4015             * Element is a generic container.
4016             */
4017            ret = XML_ELEMENT_TYPE_ANY;
4018        } else if (CUR == '(') {
4019            ret = xmlOldParseElementContentDecl(ctxt, name, &content);
4020        } else {
4021            /*
4022             * [ WFC: PEs in Internal Subset ] error handling.
4023             */
4024            if ((CUR == '%') && (ctxt->external == 0) &&
4025                (ctxt->inputNr == 1)) {
4026                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4027                    ctxt->sax->error(ctxt->userData,
4028          "PEReference: forbidden within markup decl in internal subset\n");
4029                ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
4030            } else {
4031                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4032                    ctxt->sax->error(ctxt->userData,
4033                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
4034                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
4035            }
4036            ctxt->wellFormed = 0;
4037            if (name != NULL) xmlFree(name);
4038            return(-1);
4039        }
4040
4041        SKIP_BLANKS;
4042        /*
4043         * Pop-up of finished entities.
4044         */
4045        while ((CUR == 0) && (ctxt->inputNr > 1))
4046            xmlOldPopInput(ctxt);
4047        SKIP_BLANKS;
4048
4049        if (CUR != '>') {
4050            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4051                ctxt->sax->error(ctxt->userData,
4052                  "xmlParseElementDecl: expected '>' at the end\n");
4053            ctxt->errNo = XML_ERR_GT_REQUIRED;
4054            ctxt->wellFormed = 0;
4055        } else {
4056            NEXT;
4057            if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
4058                ctxt->sax->elementDecl(ctxt->userData, name, ret,
4059                                       content);
4060        }
4061        if (content != NULL) {
4062            xmlFreeElementContent(content);
4063        }
4064        if (name != NULL) {
4065            xmlFree(name);
4066        }
4067    }
4068    return(ret);
4069}
4070
4071/**
4072 * xmlOldParseMarkupDecl:
4073 * @ctxt:  an XML parser context
4074 *
4075 * parse Markup declarations
4076 *
4077 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
4078 *                     NotationDecl | PI | Comment
4079 *
4080 * [ VC: Proper Declaration/PE Nesting ]
4081 * TODO Parameter-entity replacement text must be properly nested with
4082 * markup declarations. That is to say, if either the first character
4083 * or the last character of a markup declaration (markupdecl above) is
4084 * contained in the replacement text for a parameter-entity reference,
4085 * both must be contained in the same replacement text.
4086 *
4087 * [ WFC: PEs in Internal Subset ]
4088 * In the internal DTD subset, parameter-entity references can occur
4089 * only where markup declarations can occur, not within markup declarations.
4090 * (This does not apply to references that occur in external parameter
4091 * entities or to the external subset.)
4092 */
4093static void
4094xmlOldParseMarkupDecl(xmlParserCtxtPtr ctxt) {
4095    GROW;
4096    xmlOldParseElementDecl(ctxt);
4097    xmlOldParseAttributeListDecl(ctxt);
4098    xmlOldParseEntityDecl(ctxt);
4099    xmlOldParseNotationDecl(ctxt);
4100    xmlOldParsePI(ctxt);
4101    xmlOldParseComment(ctxt);
4102    /*
4103     * This is only for internal subset. On external entities,
4104     * the replacement is done before parsing stage
4105     */
4106    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
4107        xmlOldParsePEReference(ctxt);
4108    ctxt->instate = XML_PARSER_DTD;
4109}
4110
4111/**
4112 * xmlOldParseTextDecl:
4113 * @ctxt:  an XML parser context
4114 *
4115 * parse an XML declaration header for external entities
4116 *
4117 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
4118 *
4119 * Returns the only valuable info for an external parsed entity, the encoding
4120 */
4121
4122static xmlChar *
4123xmlOldParseTextDecl(xmlParserCtxtPtr ctxt) {
4124    xmlChar *version;
4125    xmlChar *encoding = NULL;
4126
4127    /*
4128     * We know that '<?xml' is here.
4129     */
4130    SKIP(5);
4131
4132    if (!IS_BLANK(CUR)) {
4133        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4134            ctxt->sax->error(ctxt->userData,
4135                             "Space needed after '<?xml'\n");
4136        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4137        ctxt->wellFormed = 0;
4138    }
4139    SKIP_BLANKS;
4140
4141    /*
4142     * We may have the VersionInfo here.
4143     */
4144    version = xmlOldParseVersionInfo(ctxt);
4145    if (version == NULL)
4146        version = xmlCharStrdup(XML_DEFAULT_VERSION);
4147    ctxt->version = xmlStrdup(version);
4148    xmlFree(version);
4149
4150    /*
4151     * We must have the encoding declaration
4152     */
4153    if (!IS_BLANK(CUR)) {
4154        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4155            ctxt->sax->error(ctxt->userData, "Space needed here\n");
4156        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4157        ctxt->wellFormed = 0;
4158    }
4159    encoding = xmlOldParseEncodingDecl(ctxt);
4160
4161    SKIP_BLANKS;
4162    if ((CUR == '?') && (NXT(1) == '>')) {
4163        SKIP(2);
4164    } else if (CUR == '>') {
4165        /* Deprecated old WD ... */
4166        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4167            ctxt->sax->error(ctxt->userData,
4168                             "XML declaration must end-up with '?>'\n");
4169        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
4170        ctxt->wellFormed = 0;
4171        NEXT;
4172    } else {
4173        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4174            ctxt->sax->error(ctxt->userData,
4175                             "parsing XML declaration: '?>' expected\n");
4176        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
4177        ctxt->wellFormed = 0;
4178        MOVETO_ENDTAG(CUR_PTR);
4179        NEXT;
4180    }
4181    return(encoding);
4182}
4183
4184/*
4185 * xmlOldParseConditionalSections
4186 * @ctxt:  an XML parser context
4187 *
4188 * TODO : Conditionnal section are not yet supported !
4189 *
4190 * [61] conditionalSect ::= includeSect | ignoreSect
4191 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
4192 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
4193 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
4194 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
4195 */
4196
4197static void
4198xmlOldParseConditionalSections(xmlParserCtxtPtr ctxt) {
4199    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4200        ctxt->sax->warning(ctxt->userData,
4201                           "XML conditional section not supported\n");
4202    /*
4203     * Skip up to the end of the conditionnal section.
4204     */
4205    while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>'))) {
4206        NEXT;
4207        /*
4208         * Pop-up of finished entities.
4209         */
4210        while ((CUR == 0) && (ctxt->inputNr > 1))
4211            xmlOldPopInput(ctxt);
4212
4213        if (CUR == 0)
4214            GROW;
4215    }
4216
4217    if (CUR == 0)
4218        SHRINK;
4219
4220    if (CUR == 0) {
4221        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4222            ctxt->sax->error(ctxt->userData,
4223                "XML conditional section not closed\n");
4224        ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
4225        ctxt->wellFormed = 0;
4226    } else {
4227        SKIP(3);
4228    }
4229}
4230
4231/**
4232 * xmlOldParseExternalSubset:
4233 * @ctxt:  an XML parser context
4234 * @ExternalID: the external identifier
4235 * @SystemID: the system identifier (or URL)
4236 *
4237 * parse Markup declarations from an external subset
4238 *
4239 * [30] extSubset ::= textDecl? extSubsetDecl
4240 *
4241 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
4242 */
4243void
4244xmlOldParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
4245                       const xmlChar *SystemID) {
4246    GROW;
4247    if ((CUR == '<') && (NXT(1) == '?') &&
4248        (NXT(2) == 'x') && (NXT(3) == 'm') &&
4249        (NXT(4) == 'l')) {
4250        xmlChar *decl;
4251
4252        decl = xmlOldParseTextDecl(ctxt);
4253        if (decl != NULL)
4254            xmlFree(decl);
4255    }
4256    if (ctxt->myDoc == NULL) {
4257        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
4258    }
4259    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
4260        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
4261
4262    ctxt->instate = XML_PARSER_DTD;
4263    ctxt->external = 1;
4264    while (((CUR == '<') && (NXT(1) == '?')) ||
4265           ((CUR == '<') && (NXT(1) == '!')) ||
4266           IS_BLANK(CUR)) {
4267        const xmlChar *check = CUR_PTR;
4268        int cons = ctxt->input->consumed;
4269
4270        if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4271            xmlOldParseConditionalSections(ctxt);
4272        } else if (IS_BLANK(CUR)) {
4273            NEXT;
4274        } else if (CUR == '%') {
4275            xmlOldParsePEReference(ctxt);
4276        } else
4277            xmlOldParseMarkupDecl(ctxt);
4278
4279        /*
4280         * Pop-up of finished entities.
4281         */
4282        while ((CUR == 0) && (ctxt->inputNr > 1))
4283            xmlOldPopInput(ctxt);
4284
4285        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
4286            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4287                ctxt->sax->error(ctxt->userData,
4288                    "Content error in the external subset\n");
4289            ctxt->wellFormed = 0;
4290            ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
4291            break;
4292        }
4293    }
4294   
4295    if (CUR != 0) {
4296        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4297            ctxt->sax->error(ctxt->userData,
4298                "Extra content at the end of the document\n");
4299        ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
4300        ctxt->wellFormed = 0;
4301    }
4302
4303}
4304
4305/**
4306 * xmlOldParseReference:
4307 * @ctxt:  an XML parser context
4308 *
4309 * parse and handle entity references in content, depending on the SAX
4310 * interface, this may end-up in a call to character() if this is a
4311 * CharRef, a predefined entity, if there is no reference() callback.
4312 * or if the parser was asked to switch to that mode.
4313 *
4314 * [67] Reference ::= EntityRef | CharRef
4315 */
4316static void
4317xmlOldParseReference(xmlParserCtxtPtr ctxt) {
4318    xmlEntityPtr ent;
4319    xmlChar *val;
4320    if (CUR != '&') return;
4321#if 0
4322    if (ctxt->inputNr > 1) {
4323        xmlChar cur[2] = { '&' , 0 } ;
4324
4325        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4326            ctxt->sax->characters(ctxt->userData, cur, 1);
4327        if (ctxt->token == '&')
4328            ctxt->token = 0;
4329        else {
4330            SKIP(1);
4331        }
4332        return;
4333    }
4334#endif
4335    if (NXT(1) == '#') {
4336        xmlChar out[2];
4337        int val = xmlOldParseCharRef(ctxt);
4338        /* invalid for UTF-8 variable encoding !!!!! */
4339        out[0] = val;
4340        out[1] = 0;
4341        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4342            ctxt->sax->characters(ctxt->userData, out, 1);
4343    } else {
4344        ent = xmlOldParseEntityRef(ctxt);
4345        if (ent == NULL) return;
4346        if ((ent->name != NULL) &&
4347            (ent->type != XML_INTERNAL_PREDEFINED_ENTITY)) {
4348            if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
4349                (ctxt->replaceEntities == 0)) {
4350                /*
4351                 * Create a node.
4352                 */
4353                ctxt->sax->reference(ctxt->userData, ent->name);
4354                return;
4355            } else if (ctxt->replaceEntities) {
4356                xmlParserInputPtr input;
4357
4358                input = xmlOldNewEntityInputStream(ctxt, ent);
4359                xmlOldPushInput(ctxt, input);
4360                return;
4361            }
4362        }
4363        val = ent->content;
4364        if (val == NULL) return;
4365        /*
4366         * inline the entity.
4367         */
4368        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4369            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
4370    }
4371}
4372
4373/**
4374 * xmlOldParseEntityRef:
4375 * @ctxt:  an XML parser context
4376 *
4377 * parse ENTITY references declarations
4378 *
4379 * [68] EntityRef ::= '&' Name ';'
4380 *
4381 * [ WFC: Entity Declared ]
4382 * In a document without any DTD, a document with only an internal DTD
4383 * subset which contains no parameter entity references, or a document
4384 * with "standalone='yes'", the Name given in the entity reference
4385 * must match that in an entity declaration, except that well-formed
4386 * documents need not declare any of the following entities: amp, lt,
4387 * gt, apos, quot.  The declaration of a parameter entity must precede
4388 * any reference to it.  Similarly, the declaration of a general entity
4389 * must precede any reference to it which appears in a default value in an
4390 * attribute-list declaration. Note that if entities are declared in the
4391 * external subset or in external parameter entities, a non-validating
4392 * processor is not obligated to read and process their declarations;
4393 * for such documents, the rule that an entity must be declared is a
4394 * well-formedness constraint only if standalone='yes'.
4395 *
4396 * [ WFC: Parsed Entity ]
4397 * An entity reference must not contain the name of an unparsed entity
4398 *
4399 * Returns the xmlEntityPtr if found, or NULL otherwise.
4400 */
4401static xmlEntityPtr
4402xmlOldParseEntityRef(xmlParserCtxtPtr ctxt) {
4403    xmlChar *name;
4404    xmlEntityPtr ent = NULL;
4405
4406    GROW;
4407   
4408    if (CUR == '&') {
4409        NEXT;
4410        name = xmlOldParseName(ctxt);
4411        if (name == NULL) {
4412            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4413                ctxt->sax->error(ctxt->userData,
4414                                 "xmlParseEntityRef: no name\n");
4415            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4416            ctxt->wellFormed = 0;
4417        } else {
4418            if (CUR == ';') {
4419                NEXT;
4420                /*
4421                 * Ask first SAX for entity resolution, otherwise try the
4422                 * predefined set.
4423                 */
4424                if (ctxt->sax != NULL) {
4425                    if (ctxt->sax->getEntity != NULL)
4426                        ent = ctxt->sax->getEntity(ctxt->userData, name);
4427                    if (ent == NULL)
4428                        ent = xmlGetPredefinedEntity(name);
4429                }
4430                /*
4431                 * [ WFC: Entity Declared ]
4432                 * In a document without any DTD, a document with only an
4433                 * internal DTD subset which contains no parameter entity
4434                 * references, or a document with "standalone='yes'", the
4435                 * Name given in the entity reference must match that in an
4436                 * entity declaration, except that well-formed documents
4437                 * need not declare any of the following entities: amp, lt,
4438                 * gt, apos, quot.
4439                 * The declaration of a parameter entity must precede any
4440                 * reference to it.
4441                 * Similarly, the declaration of a general entity must
4442                 * precede any reference to it which appears in a default
4443                 * value in an attribute-list declaration. Note that if
4444                 * entities are declared in the external subset or in
4445                 * external parameter entities, a non-validating processor
4446                 * is not obligated to read and process their declarations;
4447                 * for such documents, the rule that an entity must be
4448                 * declared is a well-formedness constraint only if
4449                 * standalone='yes'.
4450                 */
4451                if (ent == NULL) {
4452                    if ((ctxt->standalone == 1) ||
4453                        ((ctxt->hasExternalSubset == 0) &&
4454                         (ctxt->hasPErefs == 0))) {
4455                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4456                            ctxt->sax->error(ctxt->userData,
4457                                 "Entity '%s' not defined\n", name);
4458                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4459                        ctxt->wellFormed = 0;
4460                    } else {
4461                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4462                            ctxt->sax->warning(ctxt->userData,
4463                                 "Entity '%s' not defined\n", name);
4464                        ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
4465                    }
4466                }
4467
4468                /*
4469                 * [ WFC: Parsed Entity ]
4470                 * An entity reference must not contain the name of an
4471                 * unparsed entity
4472                 */
4473                else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4474                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4475                        ctxt->sax->error(ctxt->userData,
4476                             "Entity reference to unparsed entity %s\n", name);
4477                    ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
4478                    ctxt->wellFormed = 0;
4479                }
4480
4481                /*
4482                 * [ WFC: No External Entity References ]
4483                 * Attribute values cannot contain direct or indirect
4484                 * entity references to external entities.
4485                 */
4486                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4487                         (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4488                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4489                        ctxt->sax->error(ctxt->userData,
4490                     "Attribute references external entity '%s'\n", name);
4491                    ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
4492                    ctxt->wellFormed = 0;
4493                }
4494                /*
4495                 * [ WFC: No < in Attribute Values ]
4496                 * The replacement text of any entity referred to directly or
4497                 * indirectly in an attribute value (other than "&lt;") must
4498                 * not contain a <.
4499                 */
4500                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4501                         (ent != NULL) &&
4502                         (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
4503                         (ent->content != NULL) &&
4504                         (xmlStrchr(ent->content, '<'))) {
4505                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4506                        ctxt->sax->error(ctxt->userData,
4507         "'<' in entity '%s' is not allowed in attributes values\n", name);
4508                    ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
4509                    ctxt->wellFormed = 0;
4510                }
4511
4512                /*
4513                 * Internal check, no parameter entities here ...
4514                 */
4515                else {
4516                    switch (ent->type) {
4517                        case XML_INTERNAL_PARAMETER_ENTITY:
4518                        case XML_EXTERNAL_PARAMETER_ENTITY:
4519                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4520                            ctxt->sax->error(ctxt->userData,
4521                     "Attempt to reference the parameter entity '%s'\n", name);
4522                        ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
4523                        ctxt->wellFormed = 0;
4524                        break;
4525                    }
4526                }
4527
4528                /*
4529                 * [ WFC: No Recursion ]
4530                 * TODO A parsed entity must not contain a recursive reference
4531                 * to itself, either directly or indirectly.
4532                 */
4533
4534            } else {
4535                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4536                    ctxt->sax->error(ctxt->userData,
4537                                     "xmlParseEntityRef: expecting ';'\n");
4538                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4539                ctxt->wellFormed = 0;
4540            }
4541            xmlFree(name);
4542        }
4543    }
4544    return(ent);
4545}
4546/**
4547 * xmlOldParseStringEntityRef:
4548 * @ctxt:  an XML parser context
4549 * @str:  a pointer to an index in the string
4550 *
4551 * parse ENTITY references declarations, but this version parses it from
4552 * a string value.
4553 *
4554 * [68] EntityRef ::= '&' Name ';'
4555 *
4556 * [ WFC: Entity Declared ]
4557 * In a document without any DTD, a document with only an internal DTD
4558 * subset which contains no parameter entity references, or a document
4559 * with "standalone='yes'", the Name given in the entity reference
4560 * must match that in an entity declaration, except that well-formed
4561 * documents need not declare any of the following entities: amp, lt,
4562 * gt, apos, quot.  The declaration of a parameter entity must precede
4563 * any reference to it.  Similarly, the declaration of a general entity
4564 * must precede any reference to it which appears in a default value in an
4565 * attribute-list declaration. Note that if entities are declared in the
4566 * external subset or in external parameter entities, a non-validating
4567 * processor is not obligated to read and process their declarations;
4568 * for such documents, the rule that an entity must be declared is a
4569 * well-formedness constraint only if standalone='yes'.
4570 *
4571 * [ WFC: Parsed Entity ]
4572 * An entity reference must not contain the name of an unparsed entity
4573 *
4574 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
4575 * is updated to the current location in the string.
4576 */
4577static xmlEntityPtr
4578xmlOldParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
4579    xmlChar *name;
4580    const xmlChar *ptr;
4581    xmlChar cur;
4582    xmlEntityPtr ent = NULL;
4583
4584    GROW;
4585   
4586    if ((str == NULL) || (*str == NULL)) return(NULL); /* !!! */
4587    ptr = *str;
4588    cur = *ptr;
4589    if (cur == '&') {
4590        ptr++;
4591        cur = *ptr;
4592        name = xmlOldParseStringName(ctxt, &ptr);
4593        if (name == NULL) {
4594            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4595                ctxt->sax->error(ctxt->userData,
4596                                 "xmlParseEntityRef: no name\n");
4597            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4598            ctxt->wellFormed = 0;
4599        } else {
4600            if (CUR == ';') {
4601                NEXT;
4602                /*
4603                 * Ask first SAX for entity resolution, otherwise try the
4604                 * predefined set.
4605                 */
4606                if (ctxt->sax != NULL) {
4607                    if (ctxt->sax->getEntity != NULL)
4608                        ent = ctxt->sax->getEntity(ctxt->userData, name);
4609                    if (ent == NULL)
4610                        ent = xmlGetPredefinedEntity(name);
4611                }
4612                /*
4613                 * [ WFC: Entity Declared ]
4614                 * In a document without any DTD, a document with only an
4615                 * internal DTD subset which contains no parameter entity
4616                 * references, or a document with "standalone='yes'", the
4617                 * Name given in the entity reference must match that in an
4618                 * entity declaration, except that well-formed documents
4619                 * need not declare any of the following entities: amp, lt,
4620                 * gt, apos, quot.
4621                 * The declaration of a parameter entity must precede any
4622                 * reference to it.
4623                 * Similarly, the declaration of a general entity must
4624                 * precede any reference to it which appears in a default
4625                 * value in an attribute-list declaration. Note that if
4626                 * entities are declared in the external subset or in
4627                 * external parameter entities, a non-validating processor
4628                 * is not obligated to read and process their declarations;
4629                 * for such documents, the rule that an entity must be
4630                 * declared is a well-formedness constraint only if
4631                 * standalone='yes'.
4632                 */
4633                if (ent == NULL) {
4634                    if ((ctxt->standalone == 1) ||
4635                        ((ctxt->hasExternalSubset == 0) &&
4636                         (ctxt->hasPErefs == 0))) {
4637                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4638                            ctxt->sax->error(ctxt->userData,
4639                                 "Entity '%s' not defined\n", name);
4640                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4641                        ctxt->wellFormed = 0;
4642                    } else {
4643                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4644                            ctxt->sax->warning(ctxt->userData,
4645                                 "Entity '%s' not defined\n", name);
4646                        ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
4647                    }
4648                }
4649
4650                /*
4651                 * [ WFC: Parsed Entity ]
4652                 * An entity reference must not contain the name of an
4653                 * unparsed entity
4654                 */
4655                else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4656                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4657                        ctxt->sax->error(ctxt->userData,
4658                             "Entity reference to unparsed entity %s\n", name);
4659                    ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
4660                    ctxt->wellFormed = 0;
4661                }
4662
4663                /*
4664                 * [ WFC: No External Entity References ]
4665                 * Attribute values cannot contain direct or indirect
4666                 * entity references to external entities.
4667                 */
4668                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4669                         (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4670                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4671                        ctxt->sax->error(ctxt->userData,
4672                     "Attribute references external entity '%s'\n", name);
4673                    ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
4674                    ctxt->wellFormed = 0;
4675                }
4676                /*
4677                 * [ WFC: No < in Attribute Values ]
4678                 * The replacement text of any entity referred to directly or
4679                 * indirectly in an attribute value (other than "&lt;") must
4680                 * not contain a <.
4681                 */
4682                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4683                         (ent != NULL) &&
4684                         (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
4685                         (ent->content != NULL) &&
4686                         (xmlStrchr(ent->content, '<'))) {
4687                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4688                        ctxt->sax->error(ctxt->userData,
4689         "'<' in entity '%s' is not allowed in attributes values\n", name);
4690                    ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
4691                    ctxt->wellFormed = 0;
4692                }
4693
4694                /*
4695                 * Internal check, no parameter entities here ...
4696                 */
4697                else {
4698                    switch (ent->type) {
4699                        case XML_INTERNAL_PARAMETER_ENTITY:
4700                        case XML_EXTERNAL_PARAMETER_ENTITY:
4701                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4702                            ctxt->sax->error(ctxt->userData,
4703                     "Attempt to reference the parameter entity '%s'\n", name);
4704                        ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
4705                        ctxt->wellFormed = 0;
4706                        break;
4707                    }
4708                }
4709
4710                /*
4711                 * [ WFC: No Recursion ]
4712                 * TODO A parsed entity must not contain a recursive reference
4713                 * to itself, either directly or indirectly.
4714                 */
4715
4716            } else {
4717                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4718                    ctxt->sax->error(ctxt->userData,
4719                                     "xmlParseEntityRef: expecting ';'\n");
4720                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4721                ctxt->wellFormed = 0;
4722            }
4723            xmlFree(name);
4724        }
4725    }
4726    return(ent);
4727}
4728
4729/**
4730 * xmlOldParsePEReference:
4731 * @ctxt:  an XML parser context
4732 *
4733 * parse PEReference declarations
4734 * The entity content is handled directly by pushing it's content as
4735 * a new input stream.
4736 *
4737 * [69] PEReference ::= '%' Name ';'
4738 *
4739 * [ WFC: No Recursion ]
4740 * TODO A parsed entity must not contain a recursive
4741 * reference to itself, either directly or indirectly.
4742 *
4743 * [ WFC: Entity Declared ]
4744 * In a document without any DTD, a document with only an internal DTD
4745 * subset which contains no parameter entity references, or a document
4746 * with "standalone='yes'", ...  ... The declaration of a parameter
4747 * entity must precede any reference to it...
4748 *
4749 * [ VC: Entity Declared ]
4750 * In a document with an external subset or external parameter entities
4751 * with "standalone='no'", ...  ... The declaration of a parameter entity
4752 * must precede any reference to it...
4753 *
4754 * [ WFC: In DTD ]
4755 * Parameter-entity references may only appear in the DTD.
4756 * NOTE: misleading but this is handled.
4757 */
4758static void
4759xmlOldParsePEReference(xmlParserCtxtPtr ctxt) {
4760    xmlChar *name;
4761    xmlEntityPtr entity = NULL;
4762    xmlParserInputPtr input;
4763
4764    if (CUR == '%') {
4765        NEXT;
4766        name = xmlOldParseName(ctxt);
4767        if (name == NULL) {
4768            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4769                ctxt->sax->error(ctxt->userData,
4770                                 "xmlParsePEReference: no name\n");
4771            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4772            ctxt->wellFormed = 0;
4773        } else {
4774            if (CUR == ';') {
4775                NEXT;
4776                if ((ctxt->sax != NULL) &&
4777                    (ctxt->sax->getParameterEntity != NULL))
4778                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
4779                                                           name);
4780                if (entity == NULL) {
4781                    /*
4782                     * [ WFC: Entity Declared ]
4783                     * In a document without any DTD, a document with only an
4784                     * internal DTD subset which contains no parameter entity
4785                     * references, or a document with "standalone='yes'", ...
4786                     * ... The declaration of a parameter entity must precede
4787                     * any reference to it...
4788                     */
4789                    if ((ctxt->standalone == 1) ||
4790                        ((ctxt->hasExternalSubset == 0) &&
4791                         (ctxt->hasPErefs == 0))) {
4792                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4793                            ctxt->sax->error(ctxt->userData,
4794                             "PEReference: %%%s; not found\n", name);
4795                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4796                        ctxt->wellFormed = 0;
4797                    } else {
4798                        /*
4799                         * [ VC: Entity Declared ]
4800                         * In a document with an external subset or external
4801                         * parameter entities with "standalone='no'", ...
4802                         * ... The declaration of a parameter entity must precede
4803                         * any reference to it...
4804                         */
4805                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4806                            ctxt->sax->warning(ctxt->userData,
4807                             "PEReference: %%%s; not found\n", name);
4808                        ctxt->valid = 0;
4809                    }
4810                } else {
4811                    /*
4812                     * Internal checking in case the entity quest barfed
4813                     */
4814                    if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
4815                        (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
4816                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4817                            ctxt->sax->warning(ctxt->userData,
4818                         "Internal: %%%s; is not a parameter entity\n", name);
4819                    } else {
4820                        input = xmlOldNewEntityInputStream(ctxt, entity);
4821                        xmlOldPushInput(ctxt, input);
4822                    }
4823                }
4824                ctxt->hasPErefs = 1;
4825            } else {
4826                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4827                    ctxt->sax->error(ctxt->userData,
4828                                     "xmlParsePEReference: expecting ';'\n");
4829                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4830                ctxt->wellFormed = 0;
4831            }
4832            xmlFree(name);
4833        }
4834    }
4835}
4836
4837/**
4838 * xmlOldParseStringPEReference:
4839 * @ctxt:  an XML parser context
4840 * @str:  a pointer to an index in the string
4841 *
4842 * parse PEReference declarations
4843 *
4844 * [69] PEReference ::= '%' Name ';'
4845 *
4846 * [ WFC: No Recursion ]
4847 * TODO A parsed entity must not contain a recursive
4848 * reference to itself, either directly or indirectly.
4849 *
4850 * [ WFC: Entity Declared ]
4851 * In a document without any DTD, a document with only an internal DTD
4852 * subset which contains no parameter entity references, or a document
4853 * with "standalone='yes'", ...  ... The declaration of a parameter
4854 * entity must precede any reference to it...
4855 *
4856 * [ VC: Entity Declared ]
4857 * In a document with an external subset or external parameter entities
4858 * with "standalone='no'", ...  ... The declaration of a parameter entity
4859 * must precede any reference to it...
4860 *
4861 * [ WFC: In DTD ]
4862 * Parameter-entity references may only appear in the DTD.
4863 * NOTE: misleading but this is handled.
4864 *
4865 * Returns the string of the entity content.
4866 *         str is updated to the current value of the index
4867 */
4868static xmlEntityPtr
4869xmlOldParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
4870    const xmlChar *ptr;
4871    xmlChar cur;
4872    xmlChar *name;
4873    xmlEntityPtr entity = NULL;
4874
4875    if ((str == NULL) || (*str == NULL)) return(NULL);
4876    ptr = *str;
4877    cur = *ptr;
4878    if (cur == '%') {
4879        ptr++;
4880        cur = *ptr;
4881        name = xmlOldParseStringName(ctxt, &ptr);
4882        if (name == NULL) {
4883            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4884                ctxt->sax->error(ctxt->userData,
4885                                 "xmlParseStringPEReference: no name\n");
4886            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4887            ctxt->wellFormed = 0;
4888        } else {
4889            cur = *ptr;
4890            if (cur == ';') {
4891                ptr++;
4892                cur = *ptr;
4893                if ((ctxt->sax != NULL) &&
4894                    (ctxt->sax->getParameterEntity != NULL))
4895                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
4896                                                           name);
4897                if (entity == NULL) {
4898                    /*
4899                     * [ WFC: Entity Declared ]
4900                     * In a document without any DTD, a document with only an
4901                     * internal DTD subset which contains no parameter entity
4902                     * references, or a document with "standalone='yes'", ...
4903                     * ... The declaration of a parameter entity must precede
4904                     * any reference to it...
4905                     */
4906                    if ((ctxt->standalone == 1) ||
4907                        ((ctxt->hasExternalSubset == 0) &&
4908                         (ctxt->hasPErefs == 0))) {
4909                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4910                            ctxt->sax->error(ctxt->userData,
4911                             "PEReference: %%%s; not found\n", name);
4912                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4913                        ctxt->wellFormed = 0;
4914                    } else {
4915                        /*
4916                         * [ VC: Entity Declared ]
4917                         * In a document with an external subset or external
4918                         * parameter entities with "standalone='no'", ...
4919                         * ... The declaration of a parameter entity must
4920                         * precede any reference to it...
4921                         */
4922                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4923                            ctxt->sax->warning(ctxt->userData,
4924                             "PEReference: %%%s; not found\n", name);
4925                        ctxt->valid = 0;
4926                    }
4927                } else {
4928                    /*
4929                     * Internal checking in case the entity quest barfed
4930                     */
4931                    if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
4932                        (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
4933                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4934                            ctxt->sax->warning(ctxt->userData,
4935                         "Internal: %%%s; is not a parameter entity\n", name);
4936                    }
4937                }
4938                ctxt->hasPErefs = 1;
4939            } else {
4940                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4941                    ctxt->sax->error(ctxt->userData,
4942                                     "xmlParseStringPEReference: expecting ';'\n");
4943                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4944                ctxt->wellFormed = 0;
4945            }
4946            xmlFree(name);
4947        }
4948    }
4949    *str = ptr;
4950    return(entity);
4951}
4952
4953/**
4954 * xmlOldParseDocTypeDecl :
4955 * @ctxt:  an XML parser context
4956 *
4957 * parse a DOCTYPE declaration
4958 *
4959 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
4960 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
4961 *
4962 * [ VC: Root Element Type ]
4963 * The Name in the document type declaration must match the element
4964 * type of the root element.
4965 */
4966
4967static void
4968xmlOldParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
4969    xmlChar *name;
4970    xmlChar *ExternalID = NULL;
4971    xmlChar *URI = NULL;
4972
4973    /*
4974     * We know that '<!DOCTYPE' has been detected.
4975     */
4976    SKIP(9);
4977
4978    SKIP_BLANKS;
4979
4980    /*
4981     * Parse the DOCTYPE name.
4982     */
4983    name = xmlOldParseName(ctxt);
4984    if (name == NULL) {
4985        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4986            ctxt->sax->error(ctxt->userData,
4987                "xmlParseDocTypeDecl : no DOCTYPE name !\n");
4988        ctxt->wellFormed = 0;
4989        ctxt->errNo = XML_ERR_NAME_REQUIRED;
4990    }
4991
4992    SKIP_BLANKS;
4993
4994    /*
4995     * Check for SystemID and ExternalID
4996     */
4997    URI = xmlOldParseExternalID(ctxt, &ExternalID, 1);
4998
4999    if ((URI != NULL) || (ExternalID != NULL)) {
5000        ctxt->hasExternalSubset = 1;
5001    }
5002
5003    SKIP_BLANKS;
5004
5005    /*
5006     * NOTE: the SAX callback may try to fetch the external subset
5007     *       entity and fill it up !
5008     */
5009    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
5010        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
5011
5012    /*
5013     * Cleanup
5014     */
5015    if (URI != NULL) xmlFree(URI);
5016    if (ExternalID != NULL) xmlFree(ExternalID);
5017    if (name != NULL) xmlFree(name);
5018
5019    /*
5020     * Is there any internal subset declarations ?
5021     * they are handled separately in xmlOldParseInternalSubset()
5022     */
5023    if (CUR == '[')
5024        return;
5025
5026    /*
5027     * We should be at the end of the DOCTYPE declaration.
5028     */
5029    if (CUR != '>') {
5030        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5031            ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
5032        ctxt->wellFormed = 0;
5033        ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
5034    }
5035    NEXT;
5036}
5037
5038/**
5039 * xmlOldParseInternalsubset :
5040 * @ctxt:  an XML parser context
5041 *
5042 * parse the internal subset declaration
5043 *
5044 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
5045 */
5046
5047static void
5048xmlOldParseInternalSubset(xmlParserCtxtPtr ctxt) {
5049    /*
5050     * Is there any DTD definition ?
5051     */
5052    if (CUR == '[') {
5053        ctxt->instate = XML_PARSER_DTD;
5054        NEXT;
5055        /*
5056         * Parse the succession of Markup declarations and
5057         * PEReferences.
5058         * Subsequence (markupdecl | PEReference | S)*
5059         */
5060        while (CUR != ']') {
5061            const xmlChar *check = CUR_PTR;
5062            int cons = ctxt->input->consumed;
5063
5064            SKIP_BLANKS;
5065            xmlOldParseMarkupDecl(ctxt);
5066            xmlOldParsePEReference(ctxt);
5067
5068            /*
5069             * Pop-up of finished entities.
5070             */
5071            while ((CUR == 0) && (ctxt->inputNr > 1))
5072                xmlOldPopInput(ctxt);
5073
5074            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
5075                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5076                    ctxt->sax->error(ctxt->userData,
5077             "xmlParseInternalSubset: error detected in Markup declaration\n");
5078                ctxt->wellFormed = 0;
5079                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
5080                break;
5081            }
5082        }
5083        if (CUR == ']') NEXT;
5084    }
5085
5086    /*
5087     * We should be at the end of the DOCTYPE declaration.
5088     */
5089    if (CUR != '>') {
5090        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5091            ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
5092        ctxt->wellFormed = 0;
5093        ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
5094    }
5095    NEXT;
5096}
5097
5098/**
5099 * xmlOldParseAttribute:
5100 * @ctxt:  an XML parser context
5101 * @value:  a xmlChar ** used to store the value of the attribute
5102 *
5103 * parse an attribute
5104 *
5105 * [41] Attribute ::= Name Eq AttValue
5106 *
5107 * [ WFC: No External Entity References ]
5108 * Attribute values cannot contain direct or indirect entity references
5109 * to external entities.
5110 *
5111 * [ WFC: No < in Attribute Values ]
5112 * The replacement text of any entity referred to directly or indirectly in
5113 * an attribute value (other than "&lt;") must not contain a <.
5114 *
5115 * [ VC: Attribute Value Type ]
5116 * The attribute must have been declared; the value must be of the type
5117 * declared for it.
5118 *
5119 * [25] Eq ::= S? '=' S?
5120 *
5121 * With namespace:
5122 *
5123 * [NS 11] Attribute ::= QName Eq AttValue
5124 *
5125 * Also the case QName == xmlns:??? is handled independently as a namespace
5126 * definition.
5127 *
5128 * Returns the attribute name, and the value in *value.
5129 */
5130
5131static xmlChar *
5132xmlOldParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
5133    xmlChar *name, *val;
5134
5135    *value = NULL;
5136    name = xmlOldParseName(ctxt);
5137    if (name == NULL) {
5138        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5139            ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
5140        ctxt->wellFormed = 0;
5141        ctxt->errNo = XML_ERR_NAME_REQUIRED;
5142        return(NULL);
5143    }
5144
5145    /*
5146     * read the value
5147     */
5148    SKIP_BLANKS;
5149    if (CUR == '=') {
5150        NEXT;
5151        SKIP_BLANKS;
5152        val = xmlOldParseAttValue(ctxt);
5153        ctxt->instate = XML_PARSER_CONTENT;
5154    } else {
5155        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5156            ctxt->sax->error(ctxt->userData,
5157               "Specification mandate value for attribute %s\n", name);
5158        ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
5159        ctxt->wellFormed = 0;
5160        return(NULL);
5161    }
5162
5163    *value = val;
5164    return(name);
5165}
5166
5167/**
5168 * xmlOldParseStartTag:
5169 * @ctxt:  an XML parser context
5170 *
5171 * parse a start of tag either for rule element or
5172 * EmptyElement. In both case we don't parse the tag closing chars.
5173 *
5174 * [40] STag ::= '<' Name (S Attribute)* S? '>'
5175 *
5176 * [ WFC: Unique Att Spec ]
5177 * No attribute name may appear more than once in the same start-tag or
5178 * empty-element tag.
5179 *
5180 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
5181 *
5182 * [ WFC: Unique Att Spec ]
5183 * No attribute name may appear more than once in the same start-tag or
5184 * empty-element tag.
5185 *
5186 * With namespace:
5187 *
5188 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
5189 *
5190 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
5191 *
5192 * Returne the element name parsed
5193 */
5194
5195static xmlChar *
5196xmlOldParseStartTag(xmlParserCtxtPtr ctxt) {
5197    xmlChar *name;
5198    xmlChar *attname;
5199    xmlChar *attvalue;
5200    const xmlChar **atts = NULL;
5201    int nbatts = 0;
5202    int maxatts = 0;
5203    int i;
5204
5205    if (CUR != '<') return(NULL);
5206    NEXT;
5207
5208    name = xmlOldParseName(ctxt);
5209    if (name == NULL) {
5210        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5211            ctxt->sax->error(ctxt->userData,
5212             "xmlParseStartTag: invalid element name\n");
5213        ctxt->errNo = XML_ERR_NAME_REQUIRED;
5214        ctxt->wellFormed = 0;
5215        return(NULL);
5216    }
5217
5218    /*
5219     * Now parse the attributes, it ends up with the ending
5220     *
5221     * (S Attribute)* S?
5222     */
5223    SKIP_BLANKS;
5224    GROW;
5225    while ((IS_CHAR(CUR)) &&
5226           (CUR != '>') &&
5227           ((CUR != '/') || (NXT(1) != '>'))) {
5228        const xmlChar *q = CUR_PTR;
5229        int cons = ctxt->input->consumed;
5230
5231        attname = xmlOldParseAttribute(ctxt, &attvalue);
5232        if ((attname != NULL) && (attvalue != NULL)) {
5233            /*
5234             * [ WFC: Unique Att Spec ]
5235             * No attribute name may appear more than once in the same
5236             * start-tag or empty-element tag.
5237             */
5238            for (i = 0; i < nbatts;i += 2) {
5239                if (!xmlStrcmp(atts[i], attname)) {
5240                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5241                        ctxt->sax->error(ctxt->userData,
5242                                "Attribute %s redefined\n",
5243                                         attname);
5244                    ctxt->wellFormed = 0;
5245                    ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
5246                    xmlFree(attname);
5247                    xmlFree(attvalue);
5248                    goto failed;
5249                }
5250            }
5251
5252            /*
5253             * Add the pair to atts
5254             */
5255            if (atts == NULL) {
5256                maxatts = 10;
5257                atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
5258                if (atts == NULL) {
5259                    fprintf(stderr, "malloc of %ld byte failed\n",
5260                            maxatts * (long)sizeof(xmlChar *));
5261                    return(NULL);
5262                }
5263            } else if (nbatts + 4 > maxatts) {
5264                maxatts *= 2;
5265                atts = (const xmlChar **) xmlRealloc(atts,
5266                                                  maxatts * sizeof(xmlChar *));
5267                if (atts == NULL) {
5268                    fprintf(stderr, "realloc of %ld byte failed\n",
5269                            maxatts * (long)sizeof(xmlChar *));
5270                    return(NULL);
5271                }
5272            }
5273            atts[nbatts++] = attname;
5274            atts[nbatts++] = attvalue;
5275            atts[nbatts] = NULL;
5276            atts[nbatts + 1] = NULL;
5277        }
5278
5279failed:     
5280        SKIP_BLANKS;
5281        if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
5282            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5283                ctxt->sax->error(ctxt->userData,
5284                 "xmlParseStartTag: problem parsing attributes\n");
5285            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
5286            ctxt->wellFormed = 0;
5287            break;
5288        }
5289        GROW;
5290    }
5291
5292    /*
5293     * SAX: Start of Element !
5294     */
5295    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
5296        ctxt->sax->startElement(ctxt->userData, name, atts);
5297
5298    if (atts != NULL) {
5299        for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
5300        xmlFree(atts);
5301    }
5302    return(name);
5303}
5304
5305/**
5306 * xmlOldParseEndTag:
5307 * @ctxt:  an XML parser context
5308 *
5309 * parse an end of tag
5310 *
5311 * [42] ETag ::= '</' Name S? '>'
5312 *
5313 * With namespace
5314 *
5315 * [NS 9] ETag ::= '</' QName S? '>'
5316 */
5317
5318static void
5319xmlOldParseEndTag(xmlParserCtxtPtr ctxt) {
5320    xmlChar *name;
5321    xmlChar *oldname;
5322
5323    GROW;
5324    if ((CUR != '<') || (NXT(1) != '/')) {
5325        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5326            ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
5327        ctxt->wellFormed = 0;
5328        ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
5329        return;
5330    }
5331    SKIP(2);
5332
5333    name = xmlOldParseName(ctxt);
5334
5335    /*
5336     * We should definitely be at the ending "S? '>'" part
5337     */
5338    GROW;
5339    SKIP_BLANKS;
5340    if ((!IS_CHAR(CUR)) || (CUR != '>')) {
5341        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5342            ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
5343        ctxt->errNo = XML_ERR_GT_REQUIRED;
5344        ctxt->wellFormed = 0;
5345    } else
5346        NEXT;
5347
5348    /*
5349     * [ WFC: Element Type Match ]
5350     * The Name in an element's end-tag must match the element type in the
5351     * start-tag.
5352     *
5353     */
5354    if ((name == NULL) || (ctxt->name == NULL) ||
5355        (xmlStrcmp(name, ctxt->name))) {
5356        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
5357            if ((name != NULL) && (ctxt->name != NULL)) {
5358                ctxt->sax->error(ctxt->userData,
5359                     "Opening and ending tag mismatch: %s and %s\n",
5360                                 ctxt->name, name);
5361            } else if (ctxt->name != NULL) {
5362                ctxt->sax->error(ctxt->userData,
5363                     "Ending tag eror for: %s\n", ctxt->name);
5364            } else {
5365                ctxt->sax->error(ctxt->userData,
5366                     "Ending tag error: internal error ???\n");
5367            }
5368
5369        }     
5370        ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
5371        ctxt->wellFormed = 0;
5372    }
5373
5374    /*
5375     * SAX: End of Tag
5376     */
5377    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
5378        ctxt->sax->endElement(ctxt->userData, name);
5379
5380    if (name != NULL)
5381        xmlFree(name);
5382    oldname = nameOldPop(ctxt);
5383    if (oldname != NULL) {
5384#ifdef DEBUG_STACK
5385        fprintf(stderr,"Close: popped %s\n", oldname);
5386#endif
5387        xmlFree(oldname);
5388    }
5389    return;
5390}
5391
5392/**
5393 * xmlOldParseCDSect:
5394 * @ctxt:  an XML parser context
5395 *
5396 * Parse escaped pure raw content.
5397 *
5398 * [18] CDSect ::= CDStart CData CDEnd
5399 *
5400 * [19] CDStart ::= '<![CDATA['
5401 *
5402 * [20] Data ::= (Char* - (Char* ']]>' Char*))
5403 *
5404 * [21] CDEnd ::= ']]>'
5405 */
5406static void
5407xmlOldParseCDSect(xmlParserCtxtPtr ctxt) {
5408    xmlChar *buf = NULL;
5409    int len = 0;
5410    int size = XML_PARSER_BUFFER_SIZE;
5411    xmlChar r, s;
5412    xmlChar cur;
5413
5414    if ((NXT(0) == '<') && (NXT(1) == '!') &&
5415        (NXT(2) == '[') && (NXT(3) == 'C') &&
5416        (NXT(4) == 'D') && (NXT(5) == 'A') &&
5417        (NXT(6) == 'T') && (NXT(7) == 'A') &&
5418        (NXT(8) == '[')) {
5419        SKIP(9);
5420    } else
5421        return;
5422
5423    ctxt->instate = XML_PARSER_CDATA_SECTION;
5424    if (!IS_CHAR(CUR)) {
5425        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5426            ctxt->sax->error(ctxt->userData,
5427                             "CData section not finished\n");
5428        ctxt->wellFormed = 0;
5429        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
5430        ctxt->instate = XML_PARSER_CONTENT;
5431        return;
5432    }
5433    r = CUR;
5434    NEXT;
5435    if (!IS_CHAR(CUR)) {
5436        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5437            ctxt->sax->error(ctxt->userData,
5438                             "CData section not finished\n");
5439        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
5440        ctxt->wellFormed = 0;
5441        ctxt->instate = XML_PARSER_CONTENT;
5442        return;
5443    }
5444    s = CUR;
5445    NEXT;
5446    cur = CUR;
5447    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
5448    if (buf == NULL) {
5449        fprintf(stderr, "malloc of %d byte failed\n", size);
5450        return;
5451    }
5452    while (IS_CHAR(cur) &&
5453           ((r != ']') || (s != ']') || (cur != '>'))) {
5454        if (len + 1 >= size) {
5455            size *= 2;
5456            buf = xmlRealloc(buf, size * sizeof(xmlChar));
5457            if (buf == NULL) {
5458                fprintf(stderr, "realloc of %d byte failed\n", size);
5459                return;
5460            }
5461        }
5462        buf[len++] = r;
5463        r = s;
5464        s = cur;
5465        NEXT;
5466        cur = CUR;
5467    }
5468    buf[len] = 0;
5469    ctxt->instate = XML_PARSER_CONTENT;
5470    if (!IS_CHAR(CUR)) {
5471        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5472            ctxt->sax->error(ctxt->userData,
5473                             "CData section not finished\n%.50s\n", buf);
5474        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
5475        ctxt->wellFormed = 0;
5476        xmlFree(buf);
5477        return;
5478    }
5479    NEXT;
5480
5481    /*
5482     * Ok the buffer is to be consumed as cdata.
5483     */
5484    if (ctxt->sax != NULL) {
5485        if (ctxt->sax->cdataBlock != NULL)
5486            ctxt->sax->cdataBlock(ctxt->userData, buf, len);
5487    }
5488    xmlFree(buf);
5489}
5490
5491/**
5492 * xmlOldParseContent:
5493 * @ctxt:  an XML parser context
5494 *
5495 * Parse a content:
5496 *
5497 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
5498 */
5499
5500static void
5501xmlOldParseContent(xmlParserCtxtPtr ctxt) {
5502    GROW;
5503    while ((CUR != '<') || (NXT(1) != '/')) {
5504        const xmlChar *test = CUR_PTR;
5505        int cons = ctxt->input->consumed;
5506        int tok = ctxt->token;
5507
5508        /*
5509         * Handle  possible processed charrefs.
5510         */
5511        if (ctxt->token != 0) {
5512            xmlOldParseCharData(ctxt, 0);
5513        }
5514
5515        /*
5516         * First case : a Processing Instruction.
5517         */
5518        else if ((RAW == '<') && (NXT(1) == '?')) {
5519            xmlOldParsePI(ctxt);
5520        }
5521
5522        /*
5523         * Second case : a CDSection
5524         */
5525        else if ((RAW == '<') && (NXT(1) == '!') &&
5526            (NXT(2) == '[') && (NXT(3) == 'C') &&
5527            (NXT(4) == 'D') && (NXT(5) == 'A') &&
5528            (NXT(6) == 'T') && (NXT(7) == 'A') &&
5529            (NXT(8) == '[')) {
5530            xmlOldParseCDSect(ctxt);
5531        }
5532
5533        /*
5534         * Third case :  a comment
5535         */
5536        else if ((RAW == '<') && (NXT(1) == '!') &&
5537                 (NXT(2) == '-') && (NXT(3) == '-')) {
5538            xmlOldParseComment(ctxt);
5539            ctxt->instate = XML_PARSER_CONTENT;
5540        }
5541
5542        /*
5543         * Fourth case :  a sub-element.
5544         */
5545        else if (RAW == '<') {
5546            xmlOldParseElement(ctxt);
5547        }
5548
5549        /*
5550         * Fifth case : a reference. If if has not been resolved,
5551         *    parsing returns it's Name, create the node
5552         */
5553
5554        else if (RAW == '&') {
5555            xmlOldParseReference(ctxt);
5556        }
5557
5558        /*
5559         * Last case, text. Note that References are handled directly.
5560         */
5561        else {
5562            xmlOldParseCharData(ctxt, 0);
5563        }
5564
5565        GROW;
5566        /*
5567         * Pop-up of finished entities.
5568         */
5569        while ((RAW == 0) && (ctxt->inputNr > 1))
5570            xmlOldPopInput(ctxt);
5571        SHRINK;
5572
5573        if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
5574            (tok == ctxt->token)) {
5575            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5576                ctxt->sax->error(ctxt->userData,
5577                     "detected an error in element content\n");
5578            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
5579            ctxt->wellFormed = 0;
5580            break;
5581        }
5582    }
5583}
5584
5585/**
5586 * xmlOldParseElement:
5587 * @ctxt:  an XML parser context
5588 *
5589 * parse an XML element, this is highly recursive
5590 *
5591 * [39] element ::= EmptyElemTag | STag content ETag
5592 *
5593 * [ WFC: Element Type Match ]
5594 * The Name in an element's end-tag must match the element type in the
5595 * start-tag.
5596 *
5597 * [ VC: Element Valid ]
5598 * An element is valid if there is a declaration matching elementdecl
5599 * where the Name matches the element type and one of the following holds:
5600 *  - The declaration matches EMPTY and the element has no content.
5601 *  - The declaration matches children and the sequence of child elements
5602 *    belongs to the language generated by the regular expression in the
5603 *    content model, with optional white space (characters matching the
5604 *    nonterminal S) between each pair of child elements.
5605 *  - The declaration matches Mixed and the content consists of character
5606 *    data and child elements whose types match names in the content model.
5607 *  - The declaration matches ANY, and the types of any child elements have
5608 *    been declared.
5609 */
5610
5611static void
5612xmlOldParseElement(xmlParserCtxtPtr ctxt) {
5613    const xmlChar *openTag = CUR_PTR;
5614    xmlChar *name;
5615    xmlChar *oldname;
5616    xmlParserNodeInfo node_info;
5617    xmlNodePtr ret;
5618
5619    /* Capture start position */
5620    if (ctxt->record_info) {
5621        node_info.begin_pos = ctxt->input->consumed +
5622                          (CUR_PTR - ctxt->input->base);
5623        node_info.begin_line = ctxt->input->line;
5624    }
5625
5626    name = xmlOldParseStartTag(ctxt);
5627    if (name == NULL) {
5628        return;
5629    }
5630    nameOldPush(ctxt, name);
5631    ret = ctxt->node;
5632
5633    /*
5634     * [ VC: Root Element Type ]
5635     * The Name in the document type declaration must match the element
5636     * type of the root element.
5637     */
5638    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
5639        ctxt->node && (ctxt->node == ctxt->myDoc->root))
5640        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
5641
5642    /*
5643     * Check for an Empty Element.
5644     */
5645    if ((CUR == '/') && (NXT(1) == '>')) {
5646        SKIP(2);
5647        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
5648            ctxt->sax->endElement(ctxt->userData, name);
5649        oldname = nameOldPop(ctxt);
5650        if (oldname != NULL) {
5651#ifdef DEBUG_STACK
5652            fprintf(stderr,"Close: popped %s\n", oldname);
5653#endif
5654            xmlFree(oldname);
5655        }
5656        return;
5657    }
5658    if (CUR == '>') {
5659        NEXT;
5660    } else {
5661        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5662            ctxt->sax->error(ctxt->userData,
5663                             "Couldn't find end of Start Tag\n%.30s\n",
5664                             openTag);
5665        ctxt->wellFormed = 0;
5666        ctxt->errNo = XML_ERR_GT_REQUIRED;
5667
5668        /*
5669         * end of parsing of this node.
5670         */
5671        nodeOldPop(ctxt);
5672        oldname = nameOldPop(ctxt);
5673        if (oldname != NULL) {
5674#ifdef DEBUG_STACK
5675            fprintf(stderr,"Close: popped %s\n", oldname);
5676#endif
5677            xmlFree(oldname);
5678        }
5679
5680        /*
5681         * Capture end position and add node
5682         */
5683        if ( ret != NULL && ctxt->record_info ) {
5684           node_info.end_pos = ctxt->input->consumed +
5685                              (CUR_PTR - ctxt->input->base);
5686           node_info.end_line = ctxt->input->line;
5687           node_info.node = ret;
5688           xmlParserAddNodeInfo(ctxt, &node_info);
5689        }
5690        return;
5691    }
5692
5693    /*
5694     * Parse the content of the element:
5695     */
5696    xmlOldParseContent(ctxt);
5697    if (!IS_CHAR(CUR)) {
5698        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5699            ctxt->sax->error(ctxt->userData,
5700                 "Premature end of data in tag %.30s\n", openTag);
5701        ctxt->wellFormed = 0;
5702        ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
5703
5704        /*
5705         * end of parsing of this node.
5706         */
5707        nodeOldPop(ctxt);
5708        oldname = nameOldPop(ctxt);
5709        if (oldname != NULL) {
5710#ifdef DEBUG_STACK
5711            fprintf(stderr,"Close: popped %s\n", oldname);
5712#endif
5713            xmlFree(oldname);
5714        }
5715        return;
5716    }
5717
5718    /*
5719     * parse the end of tag: '</' should be here.
5720     */
5721    xmlOldParseEndTag(ctxt);
5722
5723    /*
5724     * Capture end position and add node
5725     */
5726    if ( ret != NULL && ctxt->record_info ) {
5727       node_info.end_pos = ctxt->input->consumed +
5728                          (CUR_PTR - ctxt->input->base);
5729       node_info.end_line = ctxt->input->line;
5730       node_info.node = ret;
5731       xmlParserAddNodeInfo(ctxt, &node_info);
5732    }
5733}
5734
5735/**
5736 * xmlOldParseVersionNum:
5737 * @ctxt:  an XML parser context
5738 *
5739 * parse the XML version value.
5740 *
5741 * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
5742 *
5743 * Returns the string giving the XML version number, or NULL
5744 */
5745static xmlChar *
5746xmlOldParseVersionNum(xmlParserCtxtPtr ctxt) {
5747    xmlChar *buf = NULL;
5748    int len = 0;
5749    int size = 10;
5750    xmlChar cur;
5751
5752    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
5753    if (buf == NULL) {
5754        fprintf(stderr, "malloc of %d byte failed\n", size);
5755        return(NULL);
5756    }
5757    cur = CUR;
5758    while (IS_CHAR(cur) &&
5759           (((cur >= 'a') && (cur <= 'z')) ||
5760            ((cur >= 'A') && (cur <= 'Z')) ||
5761            ((cur >= '0') && (cur <= '9')) ||
5762            (cur == '_') || (cur == '.') ||
5763            (cur == ':') || (cur == '-'))) {
5764        if (len + 1 >= size) {
5765            size *= 2;
5766            buf = xmlRealloc(buf, size * sizeof(xmlChar));
5767            if (buf == NULL) {
5768                fprintf(stderr, "realloc of %d byte failed\n", size);
5769                return(NULL);
5770            }
5771        }
5772        buf[len++] = cur;
5773        NEXT;
5774        cur=CUR;
5775    }
5776    buf[len] = 0;
5777    return(buf);
5778}
5779
5780/**
5781 * xmlOldParseVersionInfo:
5782 * @ctxt:  an XML parser context
5783 *
5784 * parse the XML version.
5785 *
5786 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
5787 *
5788 * [25] Eq ::= S? '=' S?
5789 *
5790 * Returns the version string, e.g. "1.0"
5791 */
5792
5793static xmlChar *
5794xmlOldParseVersionInfo(xmlParserCtxtPtr ctxt) {
5795    xmlChar *version = NULL;
5796    const xmlChar *q;
5797
5798    if ((CUR == 'v') && (NXT(1) == 'e') &&
5799        (NXT(2) == 'r') && (NXT(3) == 's') &&
5800        (NXT(4) == 'i') && (NXT(5) == 'o') &&
5801        (NXT(6) == 'n')) {
5802        SKIP(7);
5803        SKIP_BLANKS;
5804        if (CUR != '=') {
5805            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5806                ctxt->sax->error(ctxt->userData,
5807                                 "xmlParseVersionInfo : expected '='\n");
5808            ctxt->wellFormed = 0;
5809            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
5810            return(NULL);
5811        }
5812        NEXT;
5813        SKIP_BLANKS;
5814        if (CUR == '"') {
5815            NEXT;
5816            q = CUR_PTR;
5817            version = xmlOldParseVersionNum(ctxt);
5818            if (CUR != '"') {
5819                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5820                    ctxt->sax->error(ctxt->userData,
5821                                     "String not closed\n%.50s\n", q);
5822                ctxt->wellFormed = 0;
5823                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
5824            } else
5825                NEXT;
5826        } else if (CUR == '\''){
5827            NEXT;
5828            q = CUR_PTR;
5829            version = xmlOldParseVersionNum(ctxt);
5830            if (CUR != '\'') {
5831                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5832                    ctxt->sax->error(ctxt->userData,
5833                                     "String not closed\n%.50s\n", q);
5834                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
5835                ctxt->wellFormed = 0;
5836            } else
5837                NEXT;
5838        } else {
5839            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5840                ctxt->sax->error(ctxt->userData,
5841                      "xmlParseVersionInfo : expected ' or \"\n");
5842            ctxt->wellFormed = 0;
5843            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
5844        }
5845    }
5846    return(version);
5847}
5848
5849/**
5850 * xmlOldParseEncName:
5851 * @ctxt:  an XML parser context
5852 *
5853 * parse the XML encoding name
5854 *
5855 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
5856 *
5857 * Returns the encoding name value or NULL
5858 */
5859static xmlChar *
5860xmlOldParseEncName(xmlParserCtxtPtr ctxt) {
5861    xmlChar *buf = NULL;
5862    int len = 0;
5863    int size = 10;
5864    xmlChar cur;
5865
5866    cur = CUR;
5867    if (((cur >= 'a') && (cur <= 'z')) ||
5868        ((cur >= 'A') && (cur <= 'Z'))) {
5869        buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
5870        if (buf == NULL) {
5871            fprintf(stderr, "malloc of %d byte failed\n", size);
5872            return(NULL);
5873        }
5874       
5875        buf[len++] = cur;
5876        NEXT;
5877        cur = CUR;
5878        while (IS_CHAR(cur) &&
5879               (((cur >= 'a') && (cur <= 'z')) ||
5880                ((cur >= 'A') && (cur <= 'Z')) ||
5881                ((cur >= '0') && (cur <= '9')) ||
5882                (cur == '.') || (cur == '_') ||
5883                (cur == '-'))) {
5884            if (len + 1 >= size) {
5885                size *= 2;
5886                buf = xmlRealloc(buf, size * sizeof(xmlChar));
5887                if (buf == NULL) {
5888                    fprintf(stderr, "realloc of %d byte failed\n", size);
5889                    return(NULL);
5890                }
5891            }
5892            buf[len++] = cur;
5893            NEXT;
5894            cur = CUR;
5895            if (cur == 0) {
5896                SHRINK;
5897                GROW;
5898                cur = CUR;
5899            }
5900        }
5901        buf[len] = 0;
5902    } else {
5903        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5904            ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
5905        ctxt->wellFormed = 0;
5906        ctxt->errNo = XML_ERR_ENCODING_NAME;
5907    }
5908    return(buf);
5909}
5910
5911/**
5912 * xmlOldParseEncodingDecl:
5913 * @ctxt:  an XML parser context
5914 *
5915 * parse the XML encoding declaration
5916 *
5917 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
5918 *
5919 * TODO: this should setup the conversion filters.
5920 *
5921 * Returns the encoding value or NULL
5922 */
5923
5924static xmlChar *
5925xmlOldParseEncodingDecl(xmlParserCtxtPtr ctxt) {
5926    xmlChar *encoding = NULL;
5927    const xmlChar *q;
5928
5929    SKIP_BLANKS;
5930    if ((CUR == 'e') && (NXT(1) == 'n') &&
5931        (NXT(2) == 'c') && (NXT(3) == 'o') &&
5932        (NXT(4) == 'd') && (NXT(5) == 'i') &&
5933        (NXT(6) == 'n') && (NXT(7) == 'g')) {
5934        SKIP(8);
5935        SKIP_BLANKS;
5936        if (CUR != '=') {
5937            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5938                ctxt->sax->error(ctxt->userData,
5939                                 "xmlParseEncodingDecl : expected '='\n");
5940            ctxt->wellFormed = 0;
5941            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
5942            return(NULL);
5943        }
5944        NEXT;
5945        SKIP_BLANKS;
5946        if (CUR == '"') {
5947            NEXT;
5948            q = CUR_PTR;
5949            encoding = xmlOldParseEncName(ctxt);
5950            if (CUR != '"') {
5951                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5952                    ctxt->sax->error(ctxt->userData,
5953                                     "String not closed\n%.50s\n", q);
5954                ctxt->wellFormed = 0;
5955                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
5956            } else
5957                NEXT;
5958        } else if (CUR == '\''){
5959            NEXT;
5960            q = CUR_PTR;
5961            encoding = xmlOldParseEncName(ctxt);
5962            if (CUR != '\'') {
5963                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5964                    ctxt->sax->error(ctxt->userData,
5965                                     "String not closed\n%.50s\n", q);
5966                ctxt->wellFormed = 0;
5967                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
5968            } else
5969                NEXT;
5970        } else if (CUR == '"'){
5971            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5972                ctxt->sax->error(ctxt->userData,
5973                     "xmlParseEncodingDecl : expected ' or \"\n");
5974            ctxt->wellFormed = 0;
5975            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
5976        }
5977    }
5978    return(encoding);
5979}
5980
5981/**
5982 * xmlOldParseSDDecl:
5983 * @ctxt:  an XML parser context
5984 *
5985 * parse the XML standalone declaration
5986 *
5987 * [32] SDDecl ::= S 'standalone' Eq
5988 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
5989 *
5990 * [ VC: Standalone Document Declaration ]
5991 * TODO The standalone document declaration must have the value "no"
5992 * if any external markup declarations contain declarations of:
5993 *  - attributes with default values, if elements to which these
5994 *    attributes apply appear in the document without specifications
5995 *    of values for these attributes, or
5996 *  - entities (other than amp, lt, gt, apos, quot), if references
5997 *    to those entities appear in the document, or
5998 *  - attributes with values subject to normalization, where the
5999 *    attribute appears in the document with a value which will change
6000 *    as a result of normalization, or
6001 *  - element types with element content, if white space occurs directly
6002 *    within any instance of those types.
6003 *
6004 * Returns 1 if standalone, 0 otherwise
6005 */
6006
6007static int
6008xmlOldParseSDDecl(xmlParserCtxtPtr ctxt) {
6009    int standalone = -1;
6010
6011    SKIP_BLANKS;
6012    if ((CUR == 's') && (NXT(1) == 't') &&
6013        (NXT(2) == 'a') && (NXT(3) == 'n') &&
6014        (NXT(4) == 'd') && (NXT(5) == 'a') &&
6015        (NXT(6) == 'l') && (NXT(7) == 'o') &&
6016        (NXT(8) == 'n') && (NXT(9) == 'e')) {
6017        SKIP(10);
6018        SKIP_BLANKS;
6019        if (CUR != '=') {
6020            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6021                ctxt->sax->error(ctxt->userData,
6022                    "XML standalone declaration : expected '='\n");
6023            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
6024            ctxt->wellFormed = 0;
6025            return(standalone);
6026        }
6027        NEXT;
6028        SKIP_BLANKS;
6029        if (CUR == '\''){
6030            NEXT;
6031            if ((CUR == 'n') && (NXT(1) == 'o')) {
6032                standalone = 0;
6033                SKIP(2);
6034            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
6035                       (NXT(2) == 's')) {
6036                standalone = 1;
6037                SKIP(3);
6038            } else {
6039                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6040                    ctxt->sax->error(ctxt->userData,
6041                                     "standalone accepts only 'yes' or 'no'\n");
6042                ctxt->errNo = XML_ERR_STANDALONE_VALUE;
6043                ctxt->wellFormed = 0;
6044            }
6045            if (CUR != '\'') {
6046                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6047                    ctxt->sax->error(ctxt->userData, "String not closed\n");
6048                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
6049                ctxt->wellFormed = 0;
6050            } else
6051                NEXT;
6052        } else if (CUR == '"'){
6053            NEXT;
6054            if ((CUR == 'n') && (NXT(1) == 'o')) {
6055                standalone = 0;
6056                SKIP(2);
6057            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
6058                       (NXT(2) == 's')) {
6059                standalone = 1;
6060                SKIP(3);
6061            } else {
6062                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6063                    ctxt->sax->error(ctxt->userData,
6064                        "standalone accepts only 'yes' or 'no'\n");
6065                ctxt->errNo = XML_ERR_STANDALONE_VALUE;
6066                ctxt->wellFormed = 0;
6067            }
6068            if (CUR != '"') {
6069                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6070                    ctxt->sax->error(ctxt->userData, "String not closed\n");
6071                ctxt->wellFormed = 0;
6072                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
6073            } else
6074                NEXT;
6075        } else {
6076            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6077                ctxt->sax->error(ctxt->userData,
6078                                 "Standalone value not found\n");
6079            ctxt->wellFormed = 0;
6080            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
6081        }
6082    }
6083    return(standalone);
6084}
6085
6086/**
6087 * xmlOldParseXMLDecl:
6088 * @ctxt:  an XML parser context
6089 *
6090 * parse an XML declaration header
6091 *
6092 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
6093 */
6094
6095static void
6096xmlOldParseXMLDecl(xmlParserCtxtPtr ctxt) {
6097    xmlChar *version;
6098
6099    /*
6100     * We know that '<?xml' is here.
6101     */
6102    SKIP(5);
6103
6104    if (!IS_BLANK(CUR)) {
6105        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6106            ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
6107        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
6108        ctxt->wellFormed = 0;
6109    }
6110    SKIP_BLANKS;
6111
6112    /*
6113     * We should have the VersionInfo here.
6114     */
6115    version = xmlOldParseVersionInfo(ctxt);
6116    if (version == NULL)
6117        version = xmlCharStrdup(XML_DEFAULT_VERSION);
6118    ctxt->version = xmlStrdup(version);
6119    xmlFree(version);
6120
6121    /*
6122     * We may have the encoding declaration
6123     */
6124    if (!IS_BLANK(CUR)) {
6125        if ((CUR == '?') && (NXT(1) == '>')) {
6126            SKIP(2);
6127            return;
6128        }
6129        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6130            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
6131        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
6132        ctxt->wellFormed = 0;
6133    }
6134    ctxt->encoding = xmlOldParseEncodingDecl(ctxt);
6135
6136    /*
6137     * We may have the standalone status.
6138     */
6139    if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
6140        if ((CUR == '?') && (NXT(1) == '>')) {
6141            SKIP(2);
6142            return;
6143        }
6144        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6145            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
6146        ctxt->wellFormed = 0;
6147        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
6148    }
6149    SKIP_BLANKS;
6150    ctxt->standalone = xmlOldParseSDDecl(ctxt);
6151
6152    SKIP_BLANKS;
6153    if ((CUR == '?') && (NXT(1) == '>')) {
6154        SKIP(2);
6155    } else if (CUR == '>') {
6156        /* Deprecated old WD ... */
6157        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6158            ctxt->sax->error(ctxt->userData,
6159                             "XML declaration must end-up with '?>'\n");
6160        ctxt->wellFormed = 0;
6161        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
6162        NEXT;
6163    } else {
6164        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6165            ctxt->sax->error(ctxt->userData,
6166                             "parsing XML declaration: '?>' expected\n");
6167        ctxt->wellFormed = 0;
6168        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
6169        MOVETO_ENDTAG(CUR_PTR);
6170        NEXT;
6171    }
6172}
6173
6174/**
6175 * xmlOldParseMisc:
6176 * @ctxt:  an XML parser context
6177 *
6178 * parse an XML Misc* optionnal field.
6179 *
6180 * [27] Misc ::= Comment | PI |  S
6181 */
6182
6183static void
6184xmlOldParseMisc(xmlParserCtxtPtr ctxt) {
6185    while (((CUR == '<') && (NXT(1) == '?')) ||
6186           ((CUR == '<') && (NXT(1) == '!') &&
6187            (NXT(2) == '-') && (NXT(3) == '-')) ||
6188           IS_BLANK(CUR)) {
6189        if ((CUR == '<') && (NXT(1) == '?')) {
6190            xmlOldParsePI(ctxt);
6191        } else if (IS_BLANK(CUR)) {
6192            NEXT;
6193        } else
6194            xmlOldParseComment(ctxt);
6195    }
6196}
6197
6198/**
6199 * xmlOldParseDocument :
6200 * @ctxt:  an XML parser context
6201 *
6202 * parse an XML document (and build a tree if using the standard SAX
6203 * interface).
6204 *
6205 * [1] document ::= prolog element Misc*
6206 *
6207 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
6208 *
6209 * Returns 0, -1 in case of error. the parser context is augmented
6210 *                as a result of the parsing.
6211 */
6212
6213int
6214xmlOldParseDocument(xmlParserCtxtPtr ctxt) {
6215    xmlDefaultSAXHandlerInit();
6216
6217    GROW;
6218
6219    ctxt->pedantic = 0; /* we run the old 1.8.11 parser */
6220
6221    /*
6222     * SAX: beginning of the document processing.
6223     */
6224    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
6225        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
6226
6227    /*
6228     * TODO We should check for encoding here and plug-in some
6229     * conversion code !!!!
6230     */
6231
6232    /*
6233     * Wipe out everything which is before the first '<'
6234     */
6235    if (IS_BLANK(CUR)) {
6236        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6237            ctxt->sax->error(ctxt->userData,
6238            "Extra spaces at the beginning of the document are not allowed\n");
6239        ctxt->errNo = XML_ERR_DOCUMENT_START;
6240        ctxt->wellFormed = 0;
6241        SKIP_BLANKS;
6242    }
6243
6244    if (CUR == 0) {
6245        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6246            ctxt->sax->error(ctxt->userData, "Document is empty\n");
6247        ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
6248        ctxt->wellFormed = 0;
6249    }
6250
6251    /*
6252     * Check for the XMLDecl in the Prolog.
6253     */
6254    GROW;
6255    if ((CUR == '<') && (NXT(1) == '?') &&
6256        (NXT(2) == 'x') && (NXT(3) == 'm') &&
6257        (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
6258        xmlOldParseXMLDecl(ctxt);
6259        SKIP_BLANKS;
6260    } else if ((CUR == '<') && (NXT(1) == '?') &&
6261        (NXT(2) == 'X') && (NXT(3) == 'M') &&
6262        (NXT(4) == 'L') && (IS_BLANK(NXT(5)))) {
6263        /*
6264         * The first drafts were using <?XML and the final W3C REC
6265         * now use <?xml ...
6266         */
6267        xmlOldParseXMLDecl(ctxt);
6268        SKIP_BLANKS;
6269    } else {
6270        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
6271    }
6272    if ((ctxt->sax) && (ctxt->sax->startDocument))
6273        ctxt->sax->startDocument(ctxt->userData);
6274
6275    /*
6276     * The Misc part of the Prolog
6277     */
6278    GROW;
6279    xmlOldParseMisc(ctxt);
6280
6281    /*
6282     * Then possibly doc type declaration(s) and more Misc
6283     * (doctypedecl Misc*)?
6284     */
6285    GROW;
6286    if ((CUR == '<') && (NXT(1) == '!') &&
6287        (NXT(2) == 'D') && (NXT(3) == 'O') &&
6288        (NXT(4) == 'C') && (NXT(5) == 'T') &&
6289        (NXT(6) == 'Y') && (NXT(7) == 'P') &&
6290        (NXT(8) == 'E')) {
6291        xmlOldParseDocTypeDecl(ctxt);
6292        if (CUR == '[') {
6293            ctxt->instate = XML_PARSER_DTD;
6294            xmlOldParseInternalSubset(ctxt);
6295        }
6296        ctxt->instate = XML_PARSER_PROLOG;
6297        xmlOldParseMisc(ctxt);
6298    }
6299
6300    /*
6301     * Time to start parsing the tree itself
6302     */
6303    GROW;
6304    if (CUR != '<') {
6305        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6306            ctxt->sax->error(ctxt->userData,
6307                    "Start tag expect, '<' not found\n");
6308        ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
6309        ctxt->wellFormed = 0;
6310        ctxt->instate = XML_PARSER_EOF;
6311    } else {
6312        ctxt->instate = XML_PARSER_CONTENT;
6313        xmlOldParseElement(ctxt);
6314        ctxt->instate = XML_PARSER_EPILOG;
6315
6316
6317        /*
6318         * The Misc part at the end
6319         */
6320        xmlOldParseMisc(ctxt);
6321
6322        if (CUR != 0) {
6323            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6324                ctxt->sax->error(ctxt->userData,
6325                    "Extra content at the end of the document\n");
6326            ctxt->wellFormed = 0;
6327            ctxt->errNo = XML_ERR_DOCUMENT_END;
6328        }
6329        ctxt->instate = XML_PARSER_EOF;
6330    }
6331
6332    /*
6333     * SAX: end of the document processing.
6334     */
6335    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
6336        ctxt->sax->endDocument(ctxt->userData);
6337    if (! ctxt->wellFormed) return(-1);
6338    return(0);
6339}
6340
6341/************************************************************************
6342 *                                                                      *
6343 *              Progressive parsing interfaces                          *
6344 *                                                                      *
6345 ************************************************************************/
6346
6347/**
6348 * xmlOldParseLookupSequence:
6349 * @ctxt:  an XML parser context
6350 * @first:  the first char to lookup
6351 * @next:  the next char to lookup or zero
6352 * @third:  the next char to lookup or zero
6353 *
6354 * Try to find if a sequence (first, next, third) or  just (first next) or
6355 * (first) is available in the input stream.
6356 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
6357 * to avoid rescanning sequences of bytes, it DOES change the state of the
6358 * parser, do not use liberally.
6359 *
6360 * Returns the index to the current parsing point if the full sequence
6361 *      is available, -1 otherwise.
6362 */
6363static int
6364xmlOldParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
6365                       xmlChar next, xmlChar third) {
6366    int base, len;
6367    xmlParserInputPtr in;
6368    const xmlChar *buf;
6369
6370    in = ctxt->input;
6371    if (in == NULL) return(-1);
6372    base = in->cur - in->base;
6373    if (base < 0) return(-1);
6374    if (ctxt->checkIndex > base)
6375        base = ctxt->checkIndex;
6376    if (in->buf == NULL) {
6377        buf = in->base;
6378        len = in->length;
6379    } else {
6380        buf = in->buf->buffer->content;
6381        len = in->buf->buffer->use;
6382    }
6383    /* take into account the sequence length */
6384    if (third) len -= 2;
6385    else if (next) len --;
6386    for (;base < len;base++) {
6387        if (buf[base] == first) {
6388            if (third != 0) {
6389                if ((buf[base + 1] != next) ||
6390                    (buf[base + 2] != third)) continue;
6391            } else if (next != 0) {
6392                if (buf[base + 1] != next) continue;
6393            }
6394            ctxt->checkIndex = 0;
6395#ifdef DEBUG_PUSH
6396            if (next == 0)
6397                fprintf(stderr, "PP: lookup '%c' found at %d\n",
6398                        first, base);
6399            else if (third == 0)
6400                fprintf(stderr, "PP: lookup '%c%c' found at %d\n",
6401                        first, next, base);
6402            else
6403                fprintf(stderr, "PP: lookup '%c%c%c' found at %d\n",
6404                        first, next, third, base);
6405#endif
6406            return(base - (in->cur - in->base));
6407        }
6408    }
6409    ctxt->checkIndex = base;
6410#ifdef DEBUG_PUSH
6411    if (next == 0)
6412        fprintf(stderr, "PP: lookup '%c' failed\n", first);
6413    else if (third == 0)
6414        fprintf(stderr, "PP: lookup '%c%c' failed\n", first, next);
6415    else       
6416        fprintf(stderr, "PP: lookup '%c%c%c' failed\n", first, next, third);
6417#endif
6418    return(-1);
6419}
6420
6421/**
6422 * xmlOldParseTryOrFinish:
6423 * @ctxt:  an XML parser context
6424 * @terminate:  last chunk indicator
6425 *
6426 * Try to progress on parsing
6427 *
6428 * Returns zero if no parsing was possible
6429 */
6430static int
6431xmlOldParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
6432    int ret = 0;
6433    xmlParserInputPtr in;
6434    int avail;
6435    xmlChar cur, next;
6436
6437#ifdef DEBUG_PUSH
6438    switch (ctxt->instate) {
6439        case XML_PARSER_EOF:
6440            fprintf(stderr, "PP: try EOF\n"); break;
6441        case XML_PARSER_START:
6442            fprintf(stderr, "PP: try START\n"); break;
6443        case XML_PARSER_MISC:
6444            fprintf(stderr, "PP: try MISC\n");break;
6445        case XML_PARSER_COMMENT:
6446            fprintf(stderr, "PP: try COMMENT\n");break;
6447        case XML_PARSER_PROLOG:
6448            fprintf(stderr, "PP: try PROLOG\n");break;
6449        case XML_PARSER_START_TAG:
6450            fprintf(stderr, "PP: try START_TAG\n");break;
6451        case XML_PARSER_CONTENT:
6452            fprintf(stderr, "PP: try CONTENT\n");break;
6453        case XML_PARSER_CDATA_SECTION:
6454            fprintf(stderr, "PP: try CDATA_SECTION\n");break;
6455        case XML_PARSER_END_TAG:
6456            fprintf(stderr, "PP: try END_TAG\n");break;
6457        case XML_PARSER_ENTITY_DECL:
6458            fprintf(stderr, "PP: try ENTITY_DECL\n");break;
6459        case XML_PARSER_ENTITY_VALUE:
6460            fprintf(stderr, "PP: try ENTITY_VALUE\n");break;
6461        case XML_PARSER_ATTRIBUTE_VALUE:
6462            fprintf(stderr, "PP: try ATTRIBUTE_VALUE\n");break;
6463        case XML_PARSER_DTD:
6464            fprintf(stderr, "PP: try DTD\n");break;
6465        case XML_PARSER_EPILOG:
6466            fprintf(stderr, "PP: try EPILOG\n");break;
6467        case XML_PARSER_PI:
6468            fprintf(stderr, "PP: try PI\n");break;
6469    }
6470#endif
6471
6472    while (1) {
6473        /*
6474         * Pop-up of finished entities.
6475         */
6476        while ((CUR == 0) && (ctxt->inputNr > 1))
6477            xmlOldPopInput(ctxt);
6478
6479        in = ctxt->input;
6480        if (in == NULL) break;
6481        if (in->buf == NULL)
6482            avail = in->length - (in->cur - in->base);
6483        else
6484            avail = in->buf->buffer->use - (in->cur - in->base);
6485        if (avail < 1)
6486            goto done;
6487        switch (ctxt->instate) {
6488            case XML_PARSER_EOF:
6489                /*
6490                 * Document parsing is done !
6491                 */
6492                goto done;
6493            case XML_PARSER_START:
6494                /*
6495                 * Very first chars read from the document flow.
6496                 */
6497                cur = in->cur[0];
6498                if (IS_BLANK(cur)) {
6499                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
6500                        ctxt->sax->setDocumentLocator(ctxt->userData,
6501                                                      &xmlDefaultSAXLocator);
6502                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6503                        ctxt->sax->error(ctxt->userData,
6504            "Extra spaces at the beginning of the document are not allowed\n");
6505                    ctxt->errNo = XML_ERR_DOCUMENT_START;
6506                    ctxt->wellFormed = 0;
6507                    SKIP_BLANKS;
6508                    ret++;
6509                    if (in->buf == NULL)
6510                        avail = in->length - (in->cur - in->base);
6511                    else
6512                        avail = in->buf->buffer->use - (in->cur - in->base);
6513                }
6514                if (avail < 2)
6515                    goto done;
6516
6517                cur = in->cur[0];
6518                next = in->cur[1];
6519                if (cur == 0) {
6520                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
6521                        ctxt->sax->setDocumentLocator(ctxt->userData,
6522                                                      &xmlDefaultSAXLocator);
6523                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6524                        ctxt->sax->error(ctxt->userData, "Document is empty\n");
6525                    ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
6526                    ctxt->wellFormed = 0;
6527                    ctxt->instate = XML_PARSER_EOF;
6528#ifdef DEBUG_PUSH
6529                    fprintf(stderr, "PP: entering EOF\n");
6530#endif
6531                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
6532                        ctxt->sax->endDocument(ctxt->userData);
6533                    goto done;
6534                }
6535                if ((cur == '<') && (next == '?')) {
6536                    /* PI or XML decl */
6537                    if (avail < 5) return(ret);
6538                    if ((!terminate) &&
6539                        (xmlOldParseLookupSequence(ctxt, '?', '>', 0) < 0))
6540                        return(ret);
6541                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
6542                        ctxt->sax->setDocumentLocator(ctxt->userData,
6543                                                      &xmlDefaultSAXLocator);
6544                    if ((in->cur[2] == 'x') &&
6545                        (in->cur[3] == 'm') &&
6546                        (in->cur[4] == 'l') &&
6547                        (IS_BLANK(in->cur[5]))) {
6548                        ret += 5;
6549#ifdef DEBUG_PUSH
6550                        fprintf(stderr, "PP: Parsing XML Decl\n");
6551#endif
6552                        xmlOldParseXMLDecl(ctxt);
6553                        if ((ctxt->sax) && (ctxt->sax->startDocument))
6554                            ctxt->sax->startDocument(ctxt->userData);
6555                        ctxt->instate = XML_PARSER_MISC;
6556#ifdef DEBUG_PUSH
6557                        fprintf(stderr, "PP: entering MISC\n");
6558#endif
6559                    } else {
6560                        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
6561                        if ((ctxt->sax) && (ctxt->sax->startDocument))
6562                            ctxt->sax->startDocument(ctxt->userData);
6563                        ctxt->instate = XML_PARSER_MISC;
6564#ifdef DEBUG_PUSH
6565                        fprintf(stderr, "PP: entering MISC\n");
6566#endif
6567                    }
6568                } else {
6569                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
6570                        ctxt->sax->setDocumentLocator(ctxt->userData,
6571                                                      &xmlDefaultSAXLocator);
6572                    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
6573                    if ((ctxt->sax) && (ctxt->sax->startDocument))
6574                        ctxt->sax->startDocument(ctxt->userData);
6575                    ctxt->instate = XML_PARSER_MISC;
6576#ifdef DEBUG_PUSH
6577                    fprintf(stderr, "PP: entering MISC\n");
6578#endif
6579                }
6580                break;
6581            case XML_PARSER_MISC:
6582                SKIP_BLANKS;
6583                if (in->buf == NULL)
6584                    avail = in->length - (in->cur - in->base);
6585                else
6586                    avail = in->buf->buffer->use - (in->cur - in->base);
6587                if (avail < 2)
6588                    goto done;
6589                cur = in->cur[0];
6590                next = in->cur[1];
6591                if ((cur == '<') && (next == '?')) {
6592                    if ((!terminate) &&
6593                        (xmlOldParseLookupSequence(ctxt, '?', '>', 0) < 0))
6594                        goto done;
6595#ifdef DEBUG_PUSH
6596                    fprintf(stderr, "PP: Parsing PI\n");
6597#endif
6598                    xmlOldParsePI(ctxt);
6599                } else if ((cur == '<') && (next == '!') &&
6600                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
6601                    if ((!terminate) &&
6602                        (xmlOldParseLookupSequence(ctxt, '-', '-', '>') < 0))
6603                        goto done;
6604#ifdef DEBUG_PUSH
6605                    fprintf(stderr, "PP: Parsing Comment\n");
6606#endif
6607                    xmlOldParseComment(ctxt);
6608                    ctxt->instate = XML_PARSER_MISC;
6609                } else if ((cur == '<') && (next == '!') &&
6610                    (in->cur[2] == 'D') && (in->cur[3] == 'O') &&
6611                    (in->cur[4] == 'C') && (in->cur[5] == 'T') &&
6612                    (in->cur[6] == 'Y') && (in->cur[7] == 'P') &&
6613                    (in->cur[8] == 'E')) {
6614                    if ((!terminate) &&
6615                        (xmlOldParseLookupSequence(ctxt, '>', 0, 0) < 0))
6616                        goto done;
6617#ifdef DEBUG_PUSH
6618                    fprintf(stderr, "PP: Parsing internal subset\n");
6619#endif
6620                    xmlOldParseDocTypeDecl(ctxt);
6621                    if (CUR == '[') {
6622                        ctxt->instate = XML_PARSER_DTD;
6623#ifdef DEBUG_PUSH
6624                        fprintf(stderr, "PP: entering DTD\n");
6625#endif
6626                    } else {
6627                        ctxt->instate = XML_PARSER_PROLOG;
6628#ifdef DEBUG_PUSH
6629                        fprintf(stderr, "PP: entering PROLOG\n");
6630#endif
6631                    }
6632                } else if ((cur == '<') && (next == '!') &&
6633                           (avail < 9)) {
6634                    goto done;
6635                } else {
6636                    ctxt->instate = XML_PARSER_START_TAG;
6637#ifdef DEBUG_PUSH
6638                    fprintf(stderr, "PP: entering START_TAG\n");
6639#endif
6640                }
6641                break;
6642            case XML_PARSER_PROLOG:
6643                SKIP_BLANKS;
6644                if (in->buf == NULL)
6645                    avail = in->length - (in->cur - in->base);
6646                else
6647                    avail = in->buf->buffer->use - (in->cur - in->base);
6648                if (avail < 2)
6649                    goto done;
6650                cur = in->cur[0];
6651                next = in->cur[1];
6652                if ((cur == '<') && (next == '?')) {
6653                    if ((!terminate) &&
6654                        (xmlOldParseLookupSequence(ctxt, '?', '>', 0) < 0))
6655                        goto done;
6656#ifdef DEBUG_PUSH
6657                    fprintf(stderr, "PP: Parsing PI\n");
6658#endif
6659                    xmlOldParsePI(ctxt);
6660                } else if ((cur == '<') && (next == '!') &&
6661                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
6662                    if ((!terminate) &&
6663                        (xmlOldParseLookupSequence(ctxt, '-', '-', '>') < 0))
6664                        goto done;
6665#ifdef DEBUG_PUSH
6666                    fprintf(stderr, "PP: Parsing Comment\n");
6667#endif
6668                    xmlOldParseComment(ctxt);
6669                    ctxt->instate = XML_PARSER_PROLOG;
6670                } else if ((cur == '<') && (next == '!') &&
6671                           (avail < 4)) {
6672                    goto done;
6673                } else {
6674                    ctxt->instate = XML_PARSER_START_TAG;
6675#ifdef DEBUG_PUSH
6676                    fprintf(stderr, "PP: entering START_TAG\n");
6677#endif
6678                }
6679                break;
6680            case XML_PARSER_EPILOG:
6681                SKIP_BLANKS;
6682                if (in->buf == NULL)
6683                    avail = in->length - (in->cur - in->base);
6684                else
6685                    avail = in->buf->buffer->use - (in->cur - in->base);
6686                if (avail < 2)
6687                    goto done;
6688                cur = in->cur[0];
6689                next = in->cur[1];
6690                if ((cur == '<') && (next == '?')) {
6691                    if ((!terminate) &&
6692                        (xmlOldParseLookupSequence(ctxt, '?', '>', 0) < 0))
6693                        goto done;
6694#ifdef DEBUG_PUSH
6695                    fprintf(stderr, "PP: Parsing PI\n");
6696#endif
6697                    xmlOldParsePI(ctxt);
6698                    ctxt->instate = XML_PARSER_EPILOG;
6699                } else if ((cur == '<') && (next == '!') &&
6700                    (in->cur[2] == '-') && (in->cur[3] == '-')) {
6701                    if ((!terminate) &&
6702                        (xmlOldParseLookupSequence(ctxt, '-', '-', '>') < 0))
6703                        goto done;
6704#ifdef DEBUG_PUSH
6705                    fprintf(stderr, "PP: Parsing Comment\n");
6706#endif
6707                    xmlOldParseComment(ctxt);
6708                    ctxt->instate = XML_PARSER_EPILOG;
6709                } else if ((cur == '<') && (next == '!') &&
6710                           (avail < 4)) {
6711                    goto done;
6712                } else {
6713                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6714                        ctxt->sax->error(ctxt->userData,
6715                            "Extra content at the end of the document\n");
6716                    ctxt->wellFormed = 0;
6717                    ctxt->errNo = XML_ERR_DOCUMENT_END;
6718                    ctxt->instate = XML_PARSER_EOF;
6719#ifdef DEBUG_PUSH
6720                    fprintf(stderr, "PP: entering EOF\n");
6721#endif
6722                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
6723                        ctxt->sax->endDocument(ctxt->userData);
6724                    goto done;
6725                }
6726                break;
6727            case XML_PARSER_START_TAG: {
6728                xmlChar *name, *oldname;
6729
6730                if (avail < 2)
6731                    goto done;
6732                cur = in->cur[0];
6733                if (cur != '<') {
6734                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6735                        ctxt->sax->error(ctxt->userData,
6736                                "Start tag expect, '<' not found\n");
6737                    ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
6738                    ctxt->wellFormed = 0;
6739                    ctxt->instate = XML_PARSER_EOF;
6740#ifdef DEBUG_PUSH
6741                    fprintf(stderr, "PP: entering EOF\n");
6742#endif
6743                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
6744                        ctxt->sax->endDocument(ctxt->userData);
6745                    goto done;
6746                }
6747                if ((!terminate) &&
6748                    (xmlOldParseLookupSequence(ctxt, '>', 0, 0) < 0))
6749                    goto done;
6750                name = xmlOldParseStartTag(ctxt);
6751                if (name == NULL) {
6752                    ctxt->instate = XML_PARSER_EOF;
6753#ifdef DEBUG_PUSH
6754                    fprintf(stderr, "PP: entering EOF\n");
6755#endif
6756                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
6757                        ctxt->sax->endDocument(ctxt->userData);
6758                    goto done;
6759                }
6760                nameOldPush(ctxt, xmlStrdup(name));
6761
6762                /*
6763                 * [ VC: Root Element Type ]
6764                 * The Name in the document type declaration must match
6765                 * the element type of the root element.
6766                 */
6767                if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
6768                    ctxt->node && (ctxt->node == ctxt->myDoc->root))
6769                    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
6770
6771                /*
6772                 * Check for an Empty Element.
6773                 */
6774                if ((CUR == '/') && (NXT(1) == '>')) {
6775                    SKIP(2);
6776                    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
6777                        ctxt->sax->endElement(ctxt->userData, name);
6778                    xmlFree(name);
6779                    oldname = nameOldPop(ctxt);
6780                    if (oldname != NULL) {
6781#ifdef DEBUG_STACK
6782                        fprintf(stderr,"Close: popped %s\n", oldname);
6783#endif
6784                        xmlFree(oldname);
6785                    }
6786                    if (ctxt->name == NULL) {
6787                        ctxt->instate = XML_PARSER_EPILOG;
6788#ifdef DEBUG_PUSH
6789                        fprintf(stderr, "PP: entering EPILOG\n");
6790#endif
6791                    } else {
6792                        ctxt->instate = XML_PARSER_CONTENT;
6793#ifdef DEBUG_PUSH
6794                        fprintf(stderr, "PP: entering CONTENT\n");
6795#endif
6796                    }
6797                    break;
6798                }
6799                if (CUR == '>') {
6800                    NEXT;
6801                } else {
6802                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6803                        ctxt->sax->error(ctxt->userData,
6804                                         "Couldn't find end of Start Tag %s\n",
6805                                         name);
6806                    ctxt->wellFormed = 0;
6807                    ctxt->errNo = XML_ERR_GT_REQUIRED;
6808
6809                    /*
6810                     * end of parsing of this node.
6811                     */
6812                    nodeOldPop(ctxt);
6813                    oldname = nameOldPop(ctxt);
6814                    if (oldname != NULL) {
6815#ifdef DEBUG_STACK
6816                        fprintf(stderr,"Close: popped %s\n", oldname);
6817#endif
6818                        xmlFree(oldname);
6819                    }
6820                }
6821                xmlFree(name);
6822                ctxt->instate = XML_PARSER_CONTENT;
6823#ifdef DEBUG_PUSH
6824                fprintf(stderr, "PP: entering CONTENT\n");
6825#endif
6826                break;
6827            }
6828            case XML_PARSER_CONTENT:
6829                /*
6830                 * Handle preparsed entities and charRef
6831                 */
6832                if (ctxt->token != 0) {
6833                    xmlChar cur[2] = { 0 , 0 } ;
6834
6835                    cur[0] = (xmlChar) ctxt->token;
6836                    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
6837                        ctxt->sax->characters(ctxt->userData, cur, 1);
6838                    ctxt->token = 0;
6839                }
6840                if (avail < 2)
6841                    goto done;
6842                cur = in->cur[0];
6843                next = in->cur[1];
6844                if ((cur == '<') && (next == '?')) {
6845                    if ((!terminate) &&
6846                        (xmlOldParseLookupSequence(ctxt, '?', '>', 0) < 0))
6847                        goto done;
6848#ifdef DEBUG_PUSH
6849                    fprintf(stderr, "PP: Parsing PI\n");
6850#endif
6851                    xmlOldParsePI(ctxt);
6852                } else if ((cur == '<') && (next == '!') &&
6853                           (in->cur[2] == '-') && (in->cur[3] == '-')) {
6854                    if ((!terminate) &&
6855                        (xmlOldParseLookupSequence(ctxt, '-', '-', '>') < 0))
6856                        goto done;
6857#ifdef DEBUG_PUSH
6858                    fprintf(stderr, "PP: Parsing Comment\n");
6859#endif
6860                    xmlOldParseComment(ctxt);
6861                    ctxt->instate = XML_PARSER_CONTENT;
6862                } else if ((cur == '<') && (in->cur[1] == '!') &&
6863                    (in->cur[2] == '[') && (NXT(3) == 'C') &&
6864                    (in->cur[4] == 'D') && (NXT(5) == 'A') &&
6865                    (in->cur[6] == 'T') && (NXT(7) == 'A') &&
6866                    (in->cur[8] == '[')) {
6867                    SKIP(9);
6868                    ctxt->instate = XML_PARSER_CDATA_SECTION;
6869#ifdef DEBUG_PUSH
6870                    fprintf(stderr, "PP: entering CDATA_SECTION\n");
6871#endif
6872                    break;
6873                } else if ((cur == '<') && (next == '!') &&
6874                           (avail < 9)) {
6875                    goto done;
6876                } else if ((cur == '<') && (next == '/')) {
6877                    ctxt->instate = XML_PARSER_END_TAG;
6878#ifdef DEBUG_PUSH
6879                    fprintf(stderr, "PP: entering END_TAG\n");
6880#endif
6881                    break;
6882                } else if (cur == '<') {
6883                    ctxt->instate = XML_PARSER_START_TAG;
6884#ifdef DEBUG_PUSH
6885                    fprintf(stderr, "PP: entering START_TAG\n");
6886#endif
6887                    break;
6888                } else if (cur == '&') {
6889                    if ((!terminate) &&
6890                        (xmlOldParseLookupSequence(ctxt, ';', 0, 0) < 0))
6891                        goto done;
6892#ifdef DEBUG_PUSH
6893                    fprintf(stderr, "PP: Parsing Reference\n");
6894#endif
6895                    /* TODO: check generation of subtrees if noent !!! */
6896                    xmlOldParseReference(ctxt);
6897                } else {
6898                    /* TODO Avoid the extra copy, handle directly !!!!!! */
6899                    /*
6900                     * Goal of the following test is :
6901                     *  - minimize calls to the SAX 'character' callback
6902                     *    when they are mergeable
6903                     *  - handle an problem for isBlank when we only parse
6904                     *    a sequence of blank chars and the next one is
6905                     *    not available to check against '<' presence.
6906                     *  - tries to homogenize the differences in SAX
6907                     *    callbacks beween the push and pull versions
6908                     *    of the parser.
6909                     */
6910                    if ((ctxt->inputNr == 1) &&
6911                        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
6912                        if ((!terminate) &&
6913                            (xmlOldParseLookupSequence(ctxt, '<', 0, 0) < 0))
6914                            goto done;
6915                    }
6916                    ctxt->checkIndex = 0;
6917#ifdef DEBUG_PUSH
6918                    fprintf(stderr, "PP: Parsing char data\n");
6919#endif
6920                    xmlOldParseCharData(ctxt, 0);
6921                }
6922                /*
6923                 * Pop-up of finished entities.
6924                 */
6925                while ((CUR == 0) && (ctxt->inputNr > 1))
6926                    xmlOldPopInput(ctxt);
6927                break;
6928            case XML_PARSER_CDATA_SECTION: {
6929                /*
6930                 * The Push mode need to have the SAX callback for
6931                 * cdataBlock merge back contiguous callbacks.
6932                 */
6933                int base;
6934
6935                in = ctxt->input;
6936                base = xmlOldParseLookupSequence(ctxt, ']', ']', '>');
6937                if (base < 0) {
6938                    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
6939                        if (ctxt->sax != NULL) {
6940                            if (ctxt->sax->cdataBlock != NULL)
6941                                ctxt->sax->cdataBlock(ctxt->userData, in->cur,
6942                                          XML_PARSER_BIG_BUFFER_SIZE);
6943                        }
6944                        SKIP(XML_PARSER_BIG_BUFFER_SIZE);
6945                        ctxt->checkIndex = 0;
6946                    }
6947                    goto done;
6948                } else {
6949                    if ((ctxt->sax != NULL) && (base > 0)) {
6950                        if (ctxt->sax->cdataBlock != NULL)
6951                            ctxt->sax->cdataBlock(ctxt->userData,
6952                                                  in->cur, base);
6953                    }
6954                    SKIP(base + 3);
6955                    ctxt->checkIndex = 0;
6956                    ctxt->instate = XML_PARSER_CONTENT;
6957#ifdef DEBUG_PUSH
6958                    fprintf(stderr, "PP: entering CONTENT\n");
6959#endif
6960                }
6961                break;
6962            }
6963            case XML_PARSER_END_TAG:
6964                if (avail < 2)
6965                    goto done;
6966                if ((!terminate) &&
6967                    (xmlOldParseLookupSequence(ctxt, '>', 0, 0) < 0))
6968                    goto done;
6969                xmlOldParseEndTag(ctxt);
6970                if (ctxt->name == NULL) {
6971                    ctxt->instate = XML_PARSER_EPILOG;
6972#ifdef DEBUG_PUSH
6973                    fprintf(stderr, "PP: entering EPILOG\n");
6974#endif
6975                } else {
6976                    ctxt->instate = XML_PARSER_CONTENT;
6977#ifdef DEBUG_PUSH
6978                    fprintf(stderr, "PP: entering CONTENT\n");
6979#endif
6980                }
6981                break;
6982            case XML_PARSER_DTD: {
6983                /*
6984                 * Sorry but progressive parsing of the internal subset
6985                 * is not expected to be supported. We first check that
6986                 * the full content of the internal subset is available and
6987                 * the parsing is launched only at that point.
6988                 * Internal subset ends up with "']' S? '>'" in an unescaped
6989                 * section and not in a ']]>' sequence which are conditional
6990                 * sections (whoever argued to keep that crap in XML deserve
6991                 * a place in hell !).
6992                 */
6993                int base, i;
6994                xmlChar *buf;
6995                xmlChar quote = 0;
6996
6997                base = in->cur - in->base;
6998                if (base < 0) return(0);
6999                if (ctxt->checkIndex > base)
7000                    base = ctxt->checkIndex;
7001                buf = in->buf->buffer->content;
7002                for (;base < in->buf->buffer->use;base++) {
7003                    if (quote != 0) {
7004                        if (buf[base] == quote)
7005                            quote = 0;
7006                        continue;   
7007                    }
7008                    if (buf[base] == '"') {
7009                        quote = '"';
7010                        continue;
7011                    }
7012                    if (buf[base] == '\'') {
7013                        quote = '\'';
7014                        continue;
7015                    }
7016                    if (buf[base] == ']') {
7017                        if (base +1 >= in->buf->buffer->use)
7018                            break;
7019                        if (buf[base + 1] == ']') {
7020                            /* conditional crap, skip both ']' ! */
7021                            base++;
7022                            continue;
7023                        }
7024                        for (i = 0;base + i < in->buf->buffer->use;i++) {
7025                            if (buf[base + i] == '>')
7026                                goto found_end_int_subset;
7027                        }
7028                        break;
7029                    }
7030                }
7031                /*
7032                 * We didn't found the end of the Internal subset
7033                 */
7034                if (quote == 0)
7035                    ctxt->checkIndex = base;
7036#ifdef DEBUG_PUSH
7037                if (next == 0)
7038                    fprintf(stderr, "PP: lookup of int subset end filed\n");
7039#endif
7040                goto done;
7041
7042found_end_int_subset:
7043                xmlOldParseInternalSubset(ctxt);
7044                ctxt->instate = XML_PARSER_PROLOG;
7045                ctxt->checkIndex = 0;
7046#ifdef DEBUG_PUSH
7047                fprintf(stderr, "PP: entering PROLOG\n");
7048#endif
7049                break;
7050            }
7051            case XML_PARSER_COMMENT:
7052                fprintf(stderr, "PP: internal error, state == COMMENT\n");
7053                ctxt->instate = XML_PARSER_CONTENT;
7054#ifdef DEBUG_PUSH
7055                fprintf(stderr, "PP: entering CONTENT\n");
7056#endif
7057                break;
7058            case XML_PARSER_PI:
7059                fprintf(stderr, "PP: internal error, state == PI\n");
7060                ctxt->instate = XML_PARSER_CONTENT;
7061#ifdef DEBUG_PUSH
7062                fprintf(stderr, "PP: entering CONTENT\n");
7063#endif
7064                break;
7065            case XML_PARSER_ENTITY_DECL:
7066                fprintf(stderr, "PP: internal error, state == ENTITY_DECL\n");
7067                ctxt->instate = XML_PARSER_DTD;
7068#ifdef DEBUG_PUSH
7069                fprintf(stderr, "PP: entering DTD\n");
7070#endif
7071                break;
7072            case XML_PARSER_ENTITY_VALUE:
7073                fprintf(stderr, "PP: internal error, state == ENTITY_VALUE\n");
7074                ctxt->instate = XML_PARSER_CONTENT;
7075#ifdef DEBUG_PUSH
7076                fprintf(stderr, "PP: entering DTD\n");
7077#endif
7078                break;
7079            case XML_PARSER_ATTRIBUTE_VALUE:
7080                fprintf(stderr, "PP: internal error, state == ATTRIBUTE_VALUE\n");
7081                ctxt->instate = XML_PARSER_START_TAG;
7082#ifdef DEBUG_PUSH
7083                fprintf(stderr, "PP: entering START_TAG\n");
7084#endif
7085                break;
7086        }
7087    }
7088done:   
7089#ifdef DEBUG_PUSH
7090    fprintf(stderr, "PP: done %d\n", ret);
7091#endif
7092    return(ret);
7093}
7094
7095/**
7096 * xmlOldParseChunk:
7097 * @ctxt:  an XML parser context
7098 * @chunk:  an char array
7099 * @size:  the size in byte of the chunk
7100 * @terminate:  last chunk indicator
7101 *
7102 * Parse a Chunk of memory
7103 *
7104 * Returns zero if no error, the xmlParserErrors otherwise.
7105 */
7106int
7107xmlOldParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
7108              int terminate) {
7109    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
7110        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
7111        int base = ctxt->input->base - ctxt->input->buf->buffer->content;
7112        int cur = ctxt->input->cur - ctxt->input->base;
7113       
7114        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);             
7115        ctxt->input->base = ctxt->input->buf->buffer->content + base;
7116        ctxt->input->cur = ctxt->input->base + cur;
7117#ifdef DEBUG_PUSH
7118        fprintf(stderr, "PP: pushed %d\n", size);
7119#endif
7120
7121        if ((terminate) || (ctxt->input->buf->buffer->use > 80))
7122            xmlOldParseTryOrFinish(ctxt, terminate);
7123    } else if (ctxt->instate != XML_PARSER_EOF)
7124        xmlOldParseTryOrFinish(ctxt, terminate);
7125    if (terminate) {
7126        if ((ctxt->instate != XML_PARSER_EOF) &&
7127            (ctxt->instate != XML_PARSER_EPILOG)) {
7128            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7129                ctxt->sax->error(ctxt->userData,
7130                    "Extra content at the end of the document\n");
7131            ctxt->wellFormed = 0;
7132            ctxt->errNo = XML_ERR_DOCUMENT_END;
7133        }
7134        if (ctxt->instate != XML_PARSER_EOF) {
7135            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
7136                ctxt->sax->endDocument(ctxt->userData);
7137        }
7138        ctxt->instate = XML_PARSER_EOF;
7139    }
7140    return((xmlParserErrors) ctxt->errNo);           
7141}
7142
Note: See TracBrowser for help on using the repository browser.