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

Revision 17093, 197.3 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17092, which included commits to RCS files with non-trunk default branches.
RevLine 
[16737]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;
[17092]2232        if (cur == '&') { GROW; }
[16737]2233        if (ctxt->token == '&') {
2234            /*
2235             * The reparsing will be done in xmlStringGetNodeList()
2236             * called by the attribute() function in SAX.c
2237             */
2238            static xmlChar quote[6] = "&#38;";
2239
2240            if (out - buffer > buffer_size - 10) {
2241                int index = out - buffer;
2242
2243                growBuffer(buffer);
2244                out = &buffer[index];
2245            }
2246            current = &quote[0];
2247            while (*current != 0) { /* non input consuming */
2248                *out++ = *current++;
2249            }
2250            NEXT;
2251        } else if ((cur == '&') && (NXT(1) == '#')) {
2252            int val = xmlOldParseCharRef(ctxt);
2253            *out++ = val;
2254            if (out - buffer > buffer_size - 10) {
2255                int index = out - buffer;
2256
2257                growBuffer(buffer);
2258                out = &buffer[index];
2259            }
2260        } else if (cur == '&') {
2261            ent = xmlOldParseEntityRef(ctxt);
2262            if ((ent != NULL) &&
2263                (ctxt->replaceEntities != 0)) {
2264                current = ent->content;
2265                while (*current != 0) {
2266                    *out++ = *current++;
2267                    if (out - buffer > buffer_size - 10) {
2268                        int index = out - buffer;
2269
2270                        growBuffer(buffer);
2271                        out = &buffer[index];
2272                    }
2273                }
2274            } else if (ent != NULL) {
2275                int i = xmlStrlen(ent->name);
2276                const xmlChar *cur = ent->name;
2277
2278                *out++ = '&';
2279                while (out - buffer > buffer_size - i - 10) {
2280                    int index = out - buffer;
2281
2282                    growBuffer(buffer);
2283                    out = &buffer[index];
2284                }
2285                for (;i > 0;i--)
2286                    *out++ = *cur++;
2287                *out++ = ';';
2288            }
2289        } else {
2290            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
2291            if ((ctxt->token == 0) && ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9))) {
2292                *out++ = 0x20;
2293                if (out - buffer > buffer_size - 10) {
2294                  int index = out - buffer;
2295                 
2296                  growBuffer(buffer);
2297                  out = &buffer[index];
2298                }
2299            } else {
2300                *out++ = cur;
2301                if (out - buffer > buffer_size - 10) {
2302                  int index = out - buffer;
2303                 
2304                  growBuffer(buffer);
2305                  out = &buffer[index];
2306                }
2307            }
2308            NEXT;
2309        }
2310        cur = CUR;
2311    }
2312    *out++ = 0;
2313    if (CUR == '<') {
2314        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2315            ctxt->sax->error(ctxt->userData,
2316               "Unescaped '<' not allowed in attributes values\n");
2317        ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
2318        ctxt->wellFormed = 0;
2319    } else if (CUR != limit) {
2320        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2321            ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
2322        ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
2323        ctxt->wellFormed = 0;
2324    } else
2325        NEXT;
2326    return(buffer);
2327}
2328
2329/**
2330 * xmlOldParseSystemLiteral:
2331 * @ctxt:  an XML parser context
2332 *
2333 * parse an XML Literal
2334 *
2335 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
2336 *
2337 * Returns the SystemLiteral parsed or NULL
2338 */
2339
2340static xmlChar *
2341xmlOldParseSystemLiteral(xmlParserCtxtPtr ctxt) {
2342    xmlChar *buf = NULL;
2343    int len = 0;
2344    int size = XML_PARSER_BUFFER_SIZE;
2345    xmlChar cur;
2346    xmlChar stop;
2347
2348    SHRINK;
2349    if (CUR == '"') {
2350        NEXT;
2351        stop = '"';
2352    } else if (CUR == '\'') {
2353        NEXT;
2354        stop = '\'';
2355    } else {
2356        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2357            ctxt->sax->error(ctxt->userData,
2358                             "SystemLiteral \" or ' expected\n");
2359        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2360        ctxt->wellFormed = 0;
2361        return(NULL);
2362    }
2363   
2364    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2365    if (buf == NULL) {
2366        fprintf(stderr, "malloc of %d byte failed\n", size);
2367        return(NULL);
2368    }
2369    cur = CUR;
2370    while ((IS_CHAR(cur)) && (cur != stop)) {
2371        if (len + 1 >= size) {
2372            size *= 2;
2373            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2374            if (buf == NULL) {
2375                fprintf(stderr, "realloc of %d byte failed\n", size);
2376                return(NULL);
2377            }
2378        }
2379        buf[len++] = cur;
2380        NEXT;
2381        cur = CUR;
2382        if (cur == 0) {
2383            GROW;
2384            SHRINK;
2385            cur = CUR;
2386        }
2387    }
2388    buf[len] = 0;
2389    if (!IS_CHAR(cur)) {
2390        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2391            ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
2392        ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2393        ctxt->wellFormed = 0;
2394    } else {
2395        NEXT;
2396    }
2397    return(buf);
2398}
2399
2400/**
2401 * xmlOldParsePubidLiteral:
2402 * @ctxt:  an XML parser context
2403 *
2404 * parse an XML public literal
2405 *
2406 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2407 *
2408 * Returns the PubidLiteral parsed or NULL.
2409 */
2410
2411static xmlChar *
2412xmlOldParsePubidLiteral(xmlParserCtxtPtr ctxt) {
2413    xmlChar *buf = NULL;
2414    int len = 0;
2415    int size = XML_PARSER_BUFFER_SIZE;
2416    xmlChar cur;
2417    xmlChar stop;
2418
2419    SHRINK;
2420    if (CUR == '"') {
2421        NEXT;
2422        stop = '"';
2423    } else if (CUR == '\'') {
2424        NEXT;
2425        stop = '\'';
2426    } else {
2427        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2428            ctxt->sax->error(ctxt->userData,
2429                             "SystemLiteral \" or ' expected\n");
2430        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
2431        ctxt->wellFormed = 0;
2432        return(NULL);
2433    }
2434    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2435    if (buf == NULL) {
2436        fprintf(stderr, "malloc of %d byte failed\n", size);
2437        return(NULL);
2438    }
2439    cur = CUR;
2440    while ((IS_PUBIDCHAR(cur)) && (cur != stop)) {
2441        if (len + 1 >= size) {
2442            size *= 2;
2443            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2444            if (buf == NULL) {
2445                fprintf(stderr, "realloc of %d byte failed\n", size);
2446                return(NULL);
2447            }
2448        }
2449        buf[len++] = cur;
2450        NEXT;
2451        cur = CUR;
2452        if (cur == 0) {
2453            GROW;
2454            SHRINK;
2455            cur = CUR;
2456        }
2457    }
2458    buf[len] = 0;
2459    if (cur != stop) {
2460        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2461            ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
2462        ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
2463        ctxt->wellFormed = 0;
2464    } else {
2465        NEXT;
2466    }
2467    return(buf);
2468}
2469
2470/**
2471 * xmlOldParseCharData:
2472 * @ctxt:  an XML parser context
2473 * @cdata:  int indicating whether we are within a CDATA section
2474 *
2475 * parse a CharData section.
2476 * if we are within a CDATA section ']]>' marks an end of section.
2477 *
2478 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2479 */
2480
2481static void
2482xmlOldParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
2483    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE];
2484    int nbchar = 0;
2485    xmlChar cur;
2486
2487    SHRINK;
2488    cur = CUR;
2489    while (((cur != '<') || (ctxt->token == '<')) &&
2490           ((cur != '&') || (ctxt->token == '&')) &&
2491           (IS_CHAR(cur))) {
2492        if ((cur == ']') && (NXT(1) == ']') &&
2493            (NXT(2) == '>')) {
2494            if (cdata) break;
2495            else {
2496                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2497                    ctxt->sax->warning(ctxt->userData,
2498                       "Sequence ']]>' not allowed in content\n");
2499                ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
2500            }
2501        }
2502        buf[nbchar++] = CUR;
2503        if (nbchar == XML_PARSER_BIG_BUFFER_SIZE) {
2504            /*
2505             * Ok the segment is to be consumed as chars.
2506             */
2507            if (ctxt->sax != NULL) {
2508                if (areBlanksOld(ctxt, buf, nbchar)) {
2509                    if (ctxt->sax->ignorableWhitespace != NULL)
2510                        ctxt->sax->ignorableWhitespace(ctxt->userData,
2511                                                       buf, nbchar);
2512                } else {
2513                    if (ctxt->sax->characters != NULL)
2514                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
2515                }
2516            }
2517            nbchar = 0;
2518        }
2519        NEXT;
2520        cur = CUR;
2521    }
2522    if (nbchar != 0) {
2523        /*
2524         * Ok the segment is to be consumed as chars.
2525         */
2526        if (ctxt->sax != NULL) {
2527            if (areBlanksOld(ctxt, buf, nbchar)) {
2528                if (ctxt->sax->ignorableWhitespace != NULL)
2529                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2530            } else {
2531                if (ctxt->sax->characters != NULL)
2532                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
2533            }
2534        }
2535    }
2536}
2537
2538/**
2539 * xmlOldParseExternalID:
2540 * @ctxt:  an XML parser context
2541 * @publicID:  a xmlChar** receiving PubidLiteral
2542 * @strict: indicate whether we should restrict parsing to only
2543 *          production [75], see NOTE below
2544 *
2545 * Parse an External ID or a Public ID
2546 *
2547 * NOTE: Productions [75] and [83] interract badly since [75] can generate
2548 *       'PUBLIC' S PubidLiteral S SystemLiteral
2549 *
2550 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2551 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
2552 *
2553 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2554 *
2555 * Returns the function returns SystemLiteral and in the second
2556 *                case publicID receives PubidLiteral, is strict is off
2557 *                it is possible to return NULL and have publicID set.
2558 */
2559
2560static xmlChar *
2561xmlOldParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2562    xmlChar *URI = NULL;
2563
2564    SHRINK;
2565    if ((CUR == 'S') && (NXT(1) == 'Y') &&
2566         (NXT(2) == 'S') && (NXT(3) == 'T') &&
2567         (NXT(4) == 'E') && (NXT(5) == 'M')) {
2568        SKIP(6);
2569        if (!IS_BLANK(CUR)) {
2570            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2571                ctxt->sax->error(ctxt->userData,
2572                    "Space required after 'SYSTEM'\n");
2573            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2574            ctxt->wellFormed = 0;
2575        }
2576        SKIP_BLANKS;
2577        URI = xmlOldParseSystemLiteral(ctxt);
2578        if (URI == NULL) {
2579            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2580                ctxt->sax->error(ctxt->userData,
2581                  "xmlParseExternalID: SYSTEM, no URI\n");
2582            ctxt->errNo = XML_ERR_URI_REQUIRED;
2583            ctxt->wellFormed = 0;
2584        }
2585    } else if ((CUR == 'P') && (NXT(1) == 'U') &&
2586               (NXT(2) == 'B') && (NXT(3) == 'L') &&
2587               (NXT(4) == 'I') && (NXT(5) == 'C')) {
2588        SKIP(6);
2589        if (!IS_BLANK(CUR)) {
2590            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2591                ctxt->sax->error(ctxt->userData,
2592                    "Space required after 'PUBLIC'\n");
2593            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2594            ctxt->wellFormed = 0;
2595        }
2596        SKIP_BLANKS;
2597        *publicID = xmlOldParsePubidLiteral(ctxt);
2598        if (*publicID == NULL) {
2599            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2600                ctxt->sax->error(ctxt->userData,
2601                  "xmlParseExternalID: PUBLIC, no Public Identifier\n");
2602            ctxt->errNo = XML_ERR_PUBID_REQUIRED;
2603            ctxt->wellFormed = 0;
2604        }
2605        if (strict) {
2606            /*
2607             * We don't handle [83] so "S SystemLiteral" is required.
2608             */
2609            if (!IS_BLANK(CUR)) {
2610                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2611                    ctxt->sax->error(ctxt->userData,
2612                        "Space required after the Public Identifier\n");
2613                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2614                ctxt->wellFormed = 0;
2615            }
2616        } else {
2617            /*
2618             * We handle [83] so we return immediately, if
2619             * "S SystemLiteral" is not detected. From a purely parsing
2620             * point of view that's a nice mess.
2621             */
2622            const xmlChar *ptr;
2623            GROW;
2624
2625            ptr = CUR_PTR;
2626            if (!IS_BLANK(*ptr)) return(NULL);
2627           
2628            while (IS_BLANK(*ptr)) ptr++;
2629            if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
2630        }
2631        SKIP_BLANKS;
2632        URI = xmlOldParseSystemLiteral(ctxt);
2633        if (URI == NULL) {
2634            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2635                ctxt->sax->error(ctxt->userData,
2636                   "xmlParseExternalID: PUBLIC, no URI\n");
2637            ctxt->errNo = XML_ERR_URI_REQUIRED;
2638            ctxt->wellFormed = 0;
2639        }
2640    }
2641    return(URI);
2642}
2643
2644/**
2645 * xmlOldParseComment:
2646 * @ctxt:  an XML parser context
2647 *
2648 * Skip an XML (SGML) comment <!-- .... -->
2649 *  The spec says that "For compatibility, the string "--" (double-hyphen)
2650 *  must not occur within comments. "
2651 *
2652 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
2653 */
2654static void
2655xmlOldParseComment(xmlParserCtxtPtr ctxt) {
2656    xmlChar *buf = NULL;
2657    int len = 0;
2658    int size = XML_PARSER_BUFFER_SIZE;
2659    xmlChar q;
2660    xmlChar r;
2661    xmlChar cur;
2662    xmlParserInputState state;
2663
2664    /*
2665     * Check that there is a comment right here.
2666     */
2667    if ((CUR != '<') || (NXT(1) != '!') ||
2668        (NXT(2) != '-') || (NXT(3) != '-')) return;
2669
2670    state = ctxt->instate;
2671    ctxt->instate = XML_PARSER_COMMENT;
2672    SHRINK;
2673    SKIP(4);
2674    buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2675    if (buf == NULL) {
2676        fprintf(stderr, "malloc of %d byte failed\n", size);
2677        ctxt->instate = state;
2678        return;
2679    }
2680    q = CUR;
2681    NEXT;
2682    r = CUR;
2683    NEXT;
2684    cur = CUR;
2685    while (IS_CHAR(cur) &&
2686           ((cur != '>') ||
2687            (r != '-') || (q != '-'))) {
2688        if ((r == '-') && (q == '-')) {
2689            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2690                ctxt->sax->error(ctxt->userData,
2691               "Comment must not contain '--' (double-hyphen)`\n");
2692            ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
2693            ctxt->wellFormed = 0;
2694        }
2695        if (len + 1 >= size) {
2696            size *= 2;
2697            buf = xmlRealloc(buf, size * sizeof(xmlChar));
2698            if (buf == NULL) {
2699                fprintf(stderr, "realloc of %d byte failed\n", size);
2700                ctxt->instate = state;
2701                return;
2702            }
2703        }
2704        buf[len++] = q;
2705        q = r;
2706        r = cur;
2707        NEXT;
2708        cur = CUR;
2709        if (cur == 0) {
2710            SHRINK;
2711            GROW;
2712            cur = CUR;
2713        }
2714    }
2715    buf[len] = 0;
2716    if (!IS_CHAR(cur)) {
2717        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2718            ctxt->sax->error(ctxt->userData,
2719                             "Comment not terminated \n<!--%.50s\n", buf);
2720        ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
2721        ctxt->wellFormed = 0;
2722    } else {
2723        NEXT;
2724        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
2725            ctxt->sax->comment(ctxt->userData, buf);
2726        xmlFree(buf);
2727    }
2728    ctxt->instate = state;
2729}
2730
2731/**
2732 * xmlOldParsePITarget:
2733 * @ctxt:  an XML parser context
2734 *
2735 * parse the name of a PI
2736 *
2737 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
2738 *
2739 * Returns the PITarget name or NULL
2740 */
2741
2742static xmlChar *
2743xmlOldParsePITarget(xmlParserCtxtPtr ctxt) {
2744    xmlChar *name;
2745
2746    name = xmlOldParseName(ctxt);
2747    if ((name != NULL) &&
2748        ((name[0] == 'x') || (name[0] == 'X')) &&
2749        ((name[1] == 'm') || (name[1] == 'M')) &&
2750        ((name[2] == 'l') || (name[2] == 'L'))) {
2751        int i;
2752        for (i = 0;;i++) {
2753            if (xmlW3CPIs[i] == NULL) break;
2754            if (!xmlStrcmp(name, (const xmlChar *)xmlW3CPIs[i]))
2755                return(name);
2756        }
2757        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
2758            ctxt->sax->warning(ctxt->userData,
2759                 "xmlParsePItarget: invalid name prefix 'xml'\n");
2760            ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
2761        }
2762    }
2763    return(name);
2764}
2765
2766/**
2767 * xmlOldParsePI:
2768 * @ctxt:  an XML parser context
2769 *
2770 * parse an XML Processing Instruction.
2771 *
2772 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
2773 *
2774 * The processing is transfered to SAX once parsed.
2775 */
2776
2777static void
2778xmlOldParsePI(xmlParserCtxtPtr ctxt) {
2779    xmlChar *buf = NULL;
2780    int len = 0;
2781    int size = XML_PARSER_BUFFER_SIZE;
2782    xmlChar cur;
2783    xmlChar *target;
2784    xmlParserInputState state;
2785
2786    if ((CUR == '<') && (NXT(1) == '?')) {
2787        state = ctxt->instate;
2788        ctxt->instate = XML_PARSER_PI;
2789        /*
2790         * this is a Processing Instruction.
2791         */
2792        SKIP(2);
2793        SHRINK;
2794
2795        /*
2796         * Parse the target name and check for special support like
2797         * namespace.
2798         */
2799        target = xmlOldParsePITarget(ctxt);
2800        if (target != NULL) {
2801            buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2802            if (buf == NULL) {
2803                fprintf(stderr, "malloc of %d byte failed\n", size);
2804                ctxt->instate = state;
2805                return;
2806            }
2807            cur = CUR;
2808            if (!IS_BLANK(cur)) {
2809                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2810                    ctxt->sax->error(ctxt->userData,
2811                      "xmlParsePI: PI %s space expected\n", target);
2812                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2813                ctxt->wellFormed = 0;
2814            }
2815            SKIP_BLANKS;
2816            cur = CUR;
2817            while (IS_CHAR(cur) &&
2818                   ((cur != '?') || (NXT(1) != '>'))) {
2819                if (len + 1 >= size) {
2820                    size *= 2;
2821                    buf = xmlRealloc(buf, size * sizeof(xmlChar));
2822                    if (buf == NULL) {
2823                        fprintf(stderr, "realloc of %d byte failed\n", size);
2824                        ctxt->instate = state;
2825                        return;
2826                    }
2827                }
2828                buf[len++] = cur;
2829                NEXT;
2830                cur = CUR;
2831                if (cur == 0) {
2832                    SHRINK;
2833                    GROW;
2834                    cur = CUR;
2835                }
2836            }
2837            buf[len] = 0;
2838            if (!IS_CHAR(cur)) {
2839                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2840                    ctxt->sax->error(ctxt->userData,
2841                      "xmlParsePI: PI %s never end ...\n", target);
2842                ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
2843                ctxt->wellFormed = 0;
2844            } else {
2845                SKIP(2);
2846
2847                /*
2848                 * SAX: PI detected.
2849                 */
2850                if ((ctxt->sax) &&
2851                    (ctxt->sax->processingInstruction != NULL))
2852                    ctxt->sax->processingInstruction(ctxt->userData,
2853                                                     target, buf);
2854            }
2855            xmlFree(buf);
2856            xmlFree(target);
2857        } else {
2858            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2859                ctxt->sax->error(ctxt->userData,
2860                       "xmlParsePI : no target name\n");
2861            ctxt->errNo = XML_ERR_PI_NOT_STARTED;
2862            ctxt->wellFormed = 0;
2863        }
2864        ctxt->instate = state;
2865    }
2866}
2867
2868/**
2869 * xmlOldParseNotationDecl:
2870 * @ctxt:  an XML parser context
2871 *
2872 * parse a notation declaration
2873 *
2874 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
2875 *
2876 * Hence there is actually 3 choices:
2877 *     'PUBLIC' S PubidLiteral
2878 *     'PUBLIC' S PubidLiteral S SystemLiteral
2879 * and 'SYSTEM' S SystemLiteral
2880 *
2881 * See the NOTE on xmlOldParseExternalID().
2882 */
2883
2884static void
2885xmlOldParseNotationDecl(xmlParserCtxtPtr ctxt) {
2886    xmlChar *name;
2887    xmlChar *Pubid;
2888    xmlChar *Systemid;
2889   
2890    if ((CUR == '<') && (NXT(1) == '!') &&
2891        (NXT(2) == 'N') && (NXT(3) == 'O') &&
2892        (NXT(4) == 'T') && (NXT(5) == 'A') &&
2893        (NXT(6) == 'T') && (NXT(7) == 'I') &&
2894        (NXT(8) == 'O') && (NXT(9) == 'N')) {
2895        SHRINK;
2896        SKIP(10);
2897        if (!IS_BLANK(CUR)) {
2898            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2899                ctxt->sax->error(ctxt->userData,
2900                                 "Space required after '<!NOTATION'\n");
2901            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2902            ctxt->wellFormed = 0;
2903            return;
2904        }
2905        SKIP_BLANKS;
2906
2907        name = xmlOldParseName(ctxt);
2908        if (name == NULL) {
2909            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2910                ctxt->sax->error(ctxt->userData,
2911                                 "NOTATION: Name expected here\n");
2912            ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
2913            ctxt->wellFormed = 0;
2914            return;
2915        }
2916        if (!IS_BLANK(CUR)) {
2917            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2918                ctxt->sax->error(ctxt->userData,
2919                     "Space required after the NOTATION name'\n");
2920            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2921            ctxt->wellFormed = 0;
2922            return;
2923        }
2924        SKIP_BLANKS;
2925
2926        /*
2927         * Parse the IDs.
2928         */
2929        Systemid = xmlOldParseExternalID(ctxt, &Pubid, 1);
2930        SKIP_BLANKS;
2931
2932        if (CUR == '>') {
2933            NEXT;
2934            if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
2935                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
2936        } else {
2937            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2938                ctxt->sax->error(ctxt->userData,
2939                       "'>' required to close NOTATION declaration\n");
2940            ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
2941            ctxt->wellFormed = 0;
2942        }
2943        xmlFree(name);
2944        if (Systemid != NULL) xmlFree(Systemid);
2945        if (Pubid != NULL) xmlFree(Pubid);
2946    }
2947}
2948
2949/**
2950 * xmlOldParseEntityDecl:
2951 * @ctxt:  an XML parser context
2952 *
2953 * parse <!ENTITY declarations
2954 *
2955 * [70] EntityDecl ::= GEDecl | PEDecl
2956 *
2957 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
2958 *
2959 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
2960 *
2961 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
2962 *
2963 * [74] PEDef ::= EntityValue | ExternalID
2964 *
2965 * [76] NDataDecl ::= S 'NDATA' S Name
2966 *
2967 * [ VC: Notation Declared ]
2968 * The Name must match the declared name of a notation.
2969 */
2970
2971static void
2972xmlOldParseEntityDecl(xmlParserCtxtPtr ctxt) {
2973    xmlChar *name = NULL;
2974    xmlChar *value = NULL;
2975    xmlChar *URI = NULL, *literal = NULL;
2976    xmlChar *ndata = NULL;
2977    int isParameter = 0;
2978    xmlChar *orig = NULL;
2979   
2980    GROW;
2981    if ((CUR == '<') && (NXT(1) == '!') &&
2982        (NXT(2) == 'E') && (NXT(3) == 'N') &&
2983        (NXT(4) == 'T') && (NXT(5) == 'I') &&
2984        (NXT(6) == 'T') && (NXT(7) == 'Y')) {
2985        ctxt->instate = XML_PARSER_ENTITY_DECL;
2986        SHRINK;
2987        SKIP(8);
2988        if (!IS_BLANK(CUR)) {
2989            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2990                ctxt->sax->error(ctxt->userData,
2991                                 "Space required after '<!ENTITY'\n");
2992            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
2993            ctxt->wellFormed = 0;
2994        }
2995        SKIP_BLANKS;
2996
2997        if (CUR == '%') {
2998            NEXT;
2999            if (!IS_BLANK(CUR)) {
3000                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3001                    ctxt->sax->error(ctxt->userData,
3002                                     "Space required after '%'\n");
3003                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3004                ctxt->wellFormed = 0;
3005            }
3006            SKIP_BLANKS;
3007            isParameter = 1;
3008        }
3009
3010        name = xmlOldParseName(ctxt);
3011        if (name == NULL) {
3012            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3013                ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
3014            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3015            ctxt->wellFormed = 0;
3016            return;
3017        }
3018        if (!IS_BLANK(CUR)) {
3019            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3020                ctxt->sax->error(ctxt->userData,
3021                     "Space required after the entity name\n");
3022            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3023            ctxt->wellFormed = 0;
3024        }
3025        SKIP_BLANKS;
3026
3027        /*
3028         * handle the various case of definitions...
3029         */
3030        if (isParameter) {
3031            if ((CUR == '"') || (CUR == '\''))
3032                value = xmlOldParseEntityValue(ctxt, &orig);
3033                if (value) {
3034                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3035                        ctxt->sax->entityDecl(ctxt->userData, name,
3036                                    XML_INTERNAL_PARAMETER_ENTITY,
3037                                    NULL, NULL, value);
3038                }
3039            else {
3040                URI = xmlOldParseExternalID(ctxt, &literal, 1);
3041                if (URI) {
3042                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3043                        ctxt->sax->entityDecl(ctxt->userData, name,
3044                                    XML_EXTERNAL_PARAMETER_ENTITY,
3045                                    literal, URI, NULL);
3046                }
3047            }
3048        } else {
3049            if ((CUR == '"') || (CUR == '\'')) {
3050                value = xmlOldParseEntityValue(ctxt, &orig);
3051                if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3052                    ctxt->sax->entityDecl(ctxt->userData, name,
3053                                XML_INTERNAL_GENERAL_ENTITY,
3054                                NULL, NULL, value);
3055            } else {
3056                URI = xmlOldParseExternalID(ctxt, &literal, 1);
3057                if ((CUR != '>') && (!IS_BLANK(CUR))) {
3058                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3059                        ctxt->sax->error(ctxt->userData,
3060                            "Space required before 'NDATA'\n");
3061                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3062                    ctxt->wellFormed = 0;
3063                }
3064                SKIP_BLANKS;
3065                if ((CUR == 'N') && (NXT(1) == 'D') &&
3066                    (NXT(2) == 'A') && (NXT(3) == 'T') &&
3067                    (NXT(4) == 'A')) {
3068                    SKIP(5);
3069                    if (!IS_BLANK(CUR)) {
3070                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3071                            ctxt->sax->error(ctxt->userData,
3072                                "Space required after 'NDATA'\n");
3073                        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3074                        ctxt->wellFormed = 0;
3075                    }
3076                    SKIP_BLANKS;
3077                    ndata = xmlOldParseName(ctxt);
3078                    if ((ctxt->sax != NULL) &&
3079                        (ctxt->sax->unparsedEntityDecl != NULL))
3080                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
3081                                    literal, URI, ndata);
3082                } else {
3083                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
3084                        ctxt->sax->entityDecl(ctxt->userData, name,
3085                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
3086                                    literal, URI, NULL);
3087                }
3088            }
3089        }
3090        SKIP_BLANKS;
3091        if (CUR != '>') {
3092            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3093                ctxt->sax->error(ctxt->userData,
3094                    "xmlParseEntityDecl: entity %s not terminated\n", name);
3095            ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
3096            ctxt->wellFormed = 0;
3097        } else
3098            NEXT;
3099        if (orig != NULL) {
3100            /*
3101             * Ugly mechanism to save the raw entity value.
3102             */
3103            xmlEntityPtr cur = NULL;
3104
3105            if (isParameter) {
3106                if ((ctxt->sax != NULL) &&
3107                    (ctxt->sax->getParameterEntity != NULL))
3108                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
3109            } else {
3110                if ((ctxt->sax != NULL) &&
3111                    (ctxt->sax->getEntity != NULL))
3112                    cur = ctxt->sax->getEntity(ctxt->userData, name);
3113            }
3114            if (cur != NULL) {
3115                if (cur->orig != NULL)
3116                    xmlFree(orig);
3117                else
3118                    cur->orig = orig;
3119            } else
3120                xmlFree(orig);
3121        }
3122        if (name != NULL) xmlFree(name);
3123        if (value != NULL) xmlFree(value);
3124        if (URI != NULL) xmlFree(URI);
3125        if (literal != NULL) xmlFree(literal);
3126        if (ndata != NULL) xmlFree(ndata);
3127    }
3128}
3129
3130/**
3131 * xmlOldParseDefaultDecl:
3132 * @ctxt:  an XML parser context
3133 * @value:  Receive a possible fixed default value for the attribute
3134 *
3135 * Parse an attribute default declaration
3136 *
3137 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
3138 *
3139 * [ VC: Required Attribute ]
3140 * if the default declaration is the keyword #REQUIRED, then the
3141 * attribute must be specified for all elements of the type in the
3142 * attribute-list declaration.
3143 *
3144 * [ VC: Attribute Default Legal ]
3145 * The declared default value must meet the lexical constraints of
3146 * the declared attribute type c.f. xmlValidateAttributeDecl()
3147 *
3148 * [ VC: Fixed Attribute Default ]
3149 * if an attribute has a default value declared with the #FIXED
3150 * keyword, instances of that attribute must match the default value.
3151 *
3152 * [ WFC: No < in Attribute Values ]
3153 * handled in xmlOldParseAttValue()
3154 *
3155 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
3156 *          or XML_ATTRIBUTE_FIXED.
3157 */
3158
3159static int
3160xmlOldParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
3161    int val;
3162    xmlChar *ret;
3163
3164    *value = NULL;
3165    if ((CUR == '#') && (NXT(1) == 'R') &&
3166        (NXT(2) == 'E') && (NXT(3) == 'Q') &&
3167        (NXT(4) == 'U') && (NXT(5) == 'I') &&
3168        (NXT(6) == 'R') && (NXT(7) == 'E') &&
3169        (NXT(8) == 'D')) {
3170        SKIP(9);
3171        return(XML_ATTRIBUTE_REQUIRED);
3172    }
3173    if ((CUR == '#') && (NXT(1) == 'I') &&
3174        (NXT(2) == 'M') && (NXT(3) == 'P') &&
3175        (NXT(4) == 'L') && (NXT(5) == 'I') &&
3176        (NXT(6) == 'E') && (NXT(7) == 'D')) {
3177        SKIP(8);
3178        return(XML_ATTRIBUTE_IMPLIED);
3179    }
3180    val = XML_ATTRIBUTE_NONE;
3181    if ((CUR == '#') && (NXT(1) == 'F') &&
3182        (NXT(2) == 'I') && (NXT(3) == 'X') &&
3183        (NXT(4) == 'E') && (NXT(5) == 'D')) {
3184        SKIP(6);
3185        val = XML_ATTRIBUTE_FIXED;
3186        if (!IS_BLANK(CUR)) {
3187            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3188                ctxt->sax->error(ctxt->userData,
3189                                 "Space required after '#FIXED'\n");
3190            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3191            ctxt->wellFormed = 0;
3192        }
3193        SKIP_BLANKS;
3194    }
3195    ret = xmlOldParseAttValue(ctxt);
3196    ctxt->instate = XML_PARSER_DTD;
3197    if (ret == NULL) {
3198        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3199            ctxt->sax->error(ctxt->userData,
3200               "Attribute default value declaration error\n");
3201        ctxt->wellFormed = 0;
3202    } else
3203        *value = ret;
3204    return(val);
3205}
3206
3207/**
3208 * xmlOldParseNotationType:
3209 * @ctxt:  an XML parser context
3210 *
3211 * parse an Notation attribute type.
3212 *
3213 * Note: the leading 'NOTATION' S part has already being parsed...
3214 *
3215 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3216 *
3217 * [ VC: Notation Attributes ]
3218 * Values of this type must match one of the notation names included
3219 * in the declaration; all notation names in the declaration must be declared.
3220 *
3221 * Returns: the notation attribute tree built while parsing
3222 */
3223
3224static xmlEnumerationPtr
3225xmlOldParseNotationType(xmlParserCtxtPtr ctxt) {
3226    xmlChar *name;
3227    xmlEnumerationPtr ret = NULL, last = NULL, cur;
3228
3229    if (CUR != '(') {
3230        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3231            ctxt->sax->error(ctxt->userData,
3232                             "'(' required to start 'NOTATION'\n");
3233        ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
3234        ctxt->wellFormed = 0;
3235        return(NULL);
3236    }
3237    SHRINK;
3238    do {
3239        NEXT;
3240        SKIP_BLANKS;
3241        name = xmlOldParseName(ctxt);
3242        if (name == NULL) {
3243            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3244                ctxt->sax->error(ctxt->userData,
3245                                 "Name expected in NOTATION declaration\n");
3246            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3247            ctxt->wellFormed = 0;
3248            return(ret);
3249        }
3250        cur = xmlCreateEnumeration(name);
3251        xmlFree(name);
3252        if (cur == NULL) return(ret);
3253        if (last == NULL) ret = last = cur;
3254        else {
3255            last->next = cur;
3256            last = cur;
3257        }
3258        SKIP_BLANKS;
3259    } while (CUR == '|');
3260    if (CUR != ')') {
3261        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3262            ctxt->sax->error(ctxt->userData,
3263                             "')' required to finish NOTATION declaration\n");
3264        ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
3265        ctxt->wellFormed = 0;
3266        return(ret);
3267    }
3268    NEXT;
3269    return(ret);
3270}
3271
3272/**
3273 * xmlOldParseEnumerationType:
3274 * @ctxt:  an XML parser context
3275 *
3276 * parse an Enumeration attribute type.
3277 *
3278 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
3279 *
3280 * [ VC: Enumeration ]
3281 * Values of this type must match one of the Nmtoken tokens in
3282 * the declaration
3283 *
3284 * Returns: the enumeration attribute tree built while parsing
3285 */
3286
3287static xmlEnumerationPtr
3288xmlOldParseEnumerationType(xmlParserCtxtPtr ctxt) {
3289    xmlChar *name;
3290    xmlEnumerationPtr ret = NULL, last = NULL, cur;
3291
3292    if (CUR != '(') {
3293        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3294            ctxt->sax->error(ctxt->userData,
3295                             "'(' required to start ATTLIST enumeration\n");
3296        ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
3297        ctxt->wellFormed = 0;
3298        return(NULL);
3299    }
3300    SHRINK;
3301    do {
3302        NEXT;
3303        SKIP_BLANKS;
3304        name = xmlOldParseNmtoken(ctxt);
3305        if (name == NULL) {
3306            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3307                ctxt->sax->error(ctxt->userData,
3308                                 "NmToken expected in ATTLIST enumeration\n");
3309            ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
3310            ctxt->wellFormed = 0;
3311            return(ret);
3312        }
3313        cur = xmlCreateEnumeration(name);
3314        xmlFree(name);
3315        if (cur == NULL) return(ret);
3316        if (last == NULL) ret = last = cur;
3317        else {
3318            last->next = cur;
3319            last = cur;
3320        }
3321        SKIP_BLANKS;
3322    } while (CUR == '|');
3323    if (CUR != ')') {
3324        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3325            ctxt->sax->error(ctxt->userData,
3326                             "')' required to finish ATTLIST enumeration\n");
3327        ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
3328        ctxt->wellFormed = 0;
3329        return(ret);
3330    }
3331    NEXT;
3332    return(ret);
3333}
3334
3335/**
3336 * xmlOldParseEnumeratedType:
3337 * @ctxt:  an XML parser context
3338 * @tree:  the enumeration tree built while parsing
3339 *
3340 * parse an Enumerated attribute type.
3341 *
3342 * [57] EnumeratedType ::= NotationType | Enumeration
3343 *
3344 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3345 *
3346 *
3347 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
3348 */
3349
3350static int
3351xmlOldParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3352    if ((CUR == 'N') && (NXT(1) == 'O') &&
3353        (NXT(2) == 'T') && (NXT(3) == 'A') &&
3354        (NXT(4) == 'T') && (NXT(5) == 'I') &&
3355        (NXT(6) == 'O') && (NXT(7) == 'N')) {
3356        SKIP(8);
3357        if (!IS_BLANK(CUR)) {
3358            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3359                ctxt->sax->error(ctxt->userData,
3360                                 "Space required after 'NOTATION'\n");
3361            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3362            ctxt->wellFormed = 0;
3363            return(0);
3364        }
3365        SKIP_BLANKS;
3366        *tree = xmlOldParseNotationType(ctxt);
3367        if (*tree == NULL) return(0);
3368        return(XML_ATTRIBUTE_NOTATION);
3369    }
3370    *tree = xmlOldParseEnumerationType(ctxt);
3371    if (*tree == NULL) return(0);
3372    return(XML_ATTRIBUTE_ENUMERATION);
3373}
3374
3375/**
3376 * xmlOldParseAttributeType:
3377 * @ctxt:  an XML parser context
3378 * @tree:  the enumeration tree built while parsing
3379 *
3380 * parse the Attribute list def for an element
3381 *
3382 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
3383 *
3384 * [55] StringType ::= 'CDATA'
3385 *
3386 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
3387 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
3388 *
3389 * Validity constraints for attribute values syntax are checked in
3390 * xmlValidateAttributeValue()
3391 *
3392 * [ VC: ID ]
3393 * Values of type ID must match the Name production. A name must not
3394 * appear more than once in an XML document as a value of this type;
3395 * i.e., ID values must uniquely identify the elements which bear them.
3396 *
3397 * [ VC: One ID per Element Type ]
3398 * No element type may have more than one ID attribute specified.
3399 *
3400 * [ VC: ID Attribute Default ]
3401 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
3402 *
3403 * [ VC: IDREF ]
3404 * Values of type IDREF must match the Name production, and values
3405 * of type IDREFS must match Names; each IDREF Name must match the value
3406 * of an ID attribute on some element in the XML document; i.e. IDREF
3407 * values must match the value of some ID attribute.
3408 *
3409 * [ VC: Entity Name ]
3410 * Values of type ENTITY must match the Name production, values
3411 * of type ENTITIES must match Names; each Entity Name must match the
3412 * name of an unparsed entity declared in the DTD. 
3413 *
3414 * [ VC: Name Token ]
3415 * Values of type NMTOKEN must match the Nmtoken production; values
3416 * of type NMTOKENS must match Nmtokens.
3417 *
3418 * Returns the attribute type
3419 */
3420static int
3421xmlOldParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3422    SHRINK;
3423    if ((CUR == 'C') && (NXT(1) == 'D') &&
3424        (NXT(2) == 'A') && (NXT(3) == 'T') &&
3425        (NXT(4) == 'A')) {
3426        SKIP(5);
3427        return(XML_ATTRIBUTE_CDATA);
3428     } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3429        (NXT(2) == 'R') && (NXT(3) == 'E') &&
3430        (NXT(4) == 'F') && (NXT(5) == 'S')) {
3431        SKIP(6);
3432        return(XML_ATTRIBUTE_IDREFS);
3433     } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3434        (NXT(2) == 'R') && (NXT(3) == 'E') &&
3435        (NXT(4) == 'F')) {
3436        SKIP(5);
3437        return(XML_ATTRIBUTE_IDREF);
3438     } else if ((CUR == 'I') && (NXT(1) == 'D')) {
3439        SKIP(2);
3440        return(XML_ATTRIBUTE_ID);
3441     } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3442        (NXT(2) == 'T') && (NXT(3) == 'I') &&
3443        (NXT(4) == 'T') && (NXT(5) == 'Y')) {
3444        SKIP(6);
3445        return(XML_ATTRIBUTE_ENTITY);
3446     } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3447        (NXT(2) == 'T') && (NXT(3) == 'I') &&
3448        (NXT(4) == 'T') && (NXT(5) == 'I') &&
3449        (NXT(6) == 'E') && (NXT(7) == 'S')) {
3450        SKIP(8);
3451        return(XML_ATTRIBUTE_ENTITIES);
3452     } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3453        (NXT(2) == 'T') && (NXT(3) == 'O') &&
3454        (NXT(4) == 'K') && (NXT(5) == 'E') &&
3455        (NXT(6) == 'N') && (NXT(7) == 'S')) {
3456        SKIP(8);
3457        return(XML_ATTRIBUTE_NMTOKENS);
3458     } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3459        (NXT(2) == 'T') && (NXT(3) == 'O') &&
3460        (NXT(4) == 'K') && (NXT(5) == 'E') &&
3461        (NXT(6) == 'N')) {
3462        SKIP(7);
3463        return(XML_ATTRIBUTE_NMTOKEN);
3464     }
3465     return(xmlOldParseEnumeratedType(ctxt, tree));
3466}
3467
3468/**
3469 * xmlOldParseAttributeListDecl:
3470 * @ctxt:  an XML parser context
3471 *
3472 * : parse the Attribute list def for an element
3473 *
3474 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
3475 *
3476 * [53] AttDef ::= S Name S AttType S DefaultDecl
3477 *
3478 */
3479static void
3480xmlOldParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
3481    xmlChar *elemName;
3482    xmlChar *attrName;
3483    xmlEnumerationPtr tree;
3484
3485    if ((CUR == '<') && (NXT(1) == '!') &&
3486        (NXT(2) == 'A') && (NXT(3) == 'T') &&
3487        (NXT(4) == 'T') && (NXT(5) == 'L') &&
3488        (NXT(6) == 'I') && (NXT(7) == 'S') &&
3489        (NXT(8) == 'T')) {
3490        SKIP(9);
3491        if (!IS_BLANK(CUR)) {
3492            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3493                ctxt->sax->error(ctxt->userData,
3494                                 "Space required after '<!ATTLIST'\n");
3495            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3496            ctxt->wellFormed = 0;
3497        }
3498        SKIP_BLANKS;
3499        elemName = xmlOldParseName(ctxt);
3500        if (elemName == NULL) {
3501            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3502                ctxt->sax->error(ctxt->userData,
3503                                 "ATTLIST: no name for Element\n");
3504            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3505            ctxt->wellFormed = 0;
3506            return;
3507        }
3508        SKIP_BLANKS;
3509        while (CUR != '>') {
3510            const xmlChar *check = CUR_PTR;
3511            int type;
3512            int def;
3513            xmlChar *defaultValue = NULL;
3514
3515            tree = NULL;
3516            attrName = xmlOldParseName(ctxt);
3517            if (attrName == NULL) {
3518                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3519                    ctxt->sax->error(ctxt->userData,
3520                                     "ATTLIST: no name for Attribute\n");
3521                ctxt->errNo = XML_ERR_NAME_REQUIRED;
3522                ctxt->wellFormed = 0;
3523                break;
3524            }
3525            GROW;
3526            if (!IS_BLANK(CUR)) {
3527                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3528                    ctxt->sax->error(ctxt->userData,
3529                        "Space required after the attribute name\n");
3530                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3531                ctxt->wellFormed = 0;
3532                break;
3533            }
3534            SKIP_BLANKS;
3535
3536            type = xmlOldParseAttributeType(ctxt, &tree);
3537            if (type <= 0) break;
3538
3539            GROW;
3540            if (!IS_BLANK(CUR)) {
3541                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3542                    ctxt->sax->error(ctxt->userData,
3543                        "Space required after the attribute type\n");
3544                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3545                ctxt->wellFormed = 0;
3546                break;
3547            }
3548            SKIP_BLANKS;
3549
3550            def = xmlOldParseDefaultDecl(ctxt, &defaultValue);
3551            if (def <= 0) break;
3552
3553            GROW;
3554            if (CUR != '>') {
3555                if (!IS_BLANK(CUR)) {
3556                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3557                        ctxt->sax->error(ctxt->userData,
3558                        "Space required after the attribute default value\n");
3559                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3560                    ctxt->wellFormed = 0;
3561                    break;
3562                }
3563                SKIP_BLANKS;
3564            }
3565            if (check == CUR_PTR) {
3566                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3567                    ctxt->sax->error(ctxt->userData,
3568                    "xmlParseAttributeListDecl: detected internal error\n");
3569                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
3570                break;
3571            }
3572            if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
3573                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
3574                                type, def, defaultValue, tree);
3575            if (attrName != NULL)
3576                xmlFree(attrName);
3577            if (defaultValue != NULL)
3578                xmlFree(defaultValue);
3579            GROW;
3580        }
3581        if (CUR == '>')
3582            NEXT;
3583
3584        xmlFree(elemName);
3585    }
3586}
3587
3588/**
3589 * xmlOldParseElementMixedContentDecl:
3590 * @ctxt:  an XML parser context
3591 *
3592 * parse the declaration for a Mixed Element content
3593 * The leading '(' and spaces have been skipped in xmlOldParseElementContentDecl
3594 *
3595 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
3596 *                '(' S? '#PCDATA' S? ')'
3597 *
3598 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
3599 *
3600 * [ VC: No Duplicate Types ]
3601 * The same name must not appear more than once in a single
3602 * mixed-content declaration.
3603 *
3604 * returns: the list of the xmlElementContentPtr describing the element choices
3605 */
3606static xmlElementContentPtr
3607xmlOldParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
3608    xmlElementContentPtr ret = NULL, cur = NULL, n;
3609    xmlChar *elem = NULL;
3610
3611    GROW;
3612    if ((CUR == '#') && (NXT(1) == 'P') &&
3613        (NXT(2) == 'C') && (NXT(3) == 'D') &&
3614        (NXT(4) == 'A') && (NXT(5) == 'T') &&
3615        (NXT(6) == 'A')) {
3616        SKIP(7);
3617        SKIP_BLANKS;
3618        SHRINK;
3619        if (CUR == ')') {
3620            NEXT;
3621            ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3622            if (CUR == '*') {
3623                ret->ocur = XML_ELEMENT_CONTENT_MULT;
3624                NEXT;
3625            }
3626            return(ret);
3627        }
3628        if ((CUR == '(') || (CUR == '|')) {
3629            ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3630            if (ret == NULL) return(NULL);
3631        }
3632        while (CUR == '|') {
3633            NEXT;
3634            if (elem == NULL) {
3635                ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3636                if (ret == NULL) return(NULL);
3637                ret->c1 = cur;
3638                cur = ret;
3639            } else {
3640                n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3641                if (n == NULL) return(NULL);
3642                n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3643                cur->c2 = n;
3644                cur = n;
3645                xmlFree(elem);
3646            }
3647            SKIP_BLANKS;
3648            elem = xmlOldParseName(ctxt);
3649            if (elem == NULL) {
3650                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3651                    ctxt->sax->error(ctxt->userData,
3652                        "xmlParseElementMixedContentDecl : Name expected\n");
3653                ctxt->errNo = XML_ERR_NAME_REQUIRED;
3654                ctxt->wellFormed = 0;
3655                xmlFreeElementContent(cur);
3656                return(NULL);
3657            }
3658            SKIP_BLANKS;
3659            GROW;
3660        }
3661        if ((CUR == ')') && (NXT(1) == '*')) {
3662            if (elem != NULL) {
3663                cur->c2 = xmlNewElementContent(elem,
3664                                               XML_ELEMENT_CONTENT_ELEMENT);
3665                xmlFree(elem);
3666            }
3667            ret->ocur = XML_ELEMENT_CONTENT_MULT;
3668            SKIP(2);
3669        } else {
3670            if (elem != NULL) xmlFree(elem);
3671            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3672                ctxt->sax->error(ctxt->userData,
3673                    "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
3674            ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
3675            ctxt->wellFormed = 0;
3676            xmlFreeElementContent(ret);
3677            return(NULL);
3678        }
3679
3680    } else {
3681        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3682            ctxt->sax->error(ctxt->userData,
3683                "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
3684        ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
3685        ctxt->wellFormed = 0;
3686    }
3687    return(ret);
3688}
3689
3690/**
3691 * xmlOldParseElementChildrenContentDecl:
3692 * @ctxt:  an XML parser context
3693 *
3694 * parse the declaration for a Mixed Element content
3695 * The leading '(' and spaces have been skipped in xmlOldParseElementContentDecl
3696 *
3697 *
3698 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
3699 *
3700 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
3701 *
3702 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
3703 *
3704 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
3705 *
3706 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
3707 * TODO Parameter-entity replacement text must be properly nested
3708 *      with parenthetized groups. That is to say, if either of the
3709 *      opening or closing parentheses in a choice, seq, or Mixed
3710 *      construct is contained in the replacement text for a parameter
3711 *      entity, both must be contained in the same replacement text. For
3712 *      interoperability, if a parameter-entity reference appears in a
3713 *      choice, seq, or Mixed construct, its replacement text should not
3714 *      be empty, and neither the first nor last non-blank character of
3715 *      the replacement text should be a connector (| or ,).
3716 *
3717 * returns: the tree of xmlElementContentPtr describing the element
3718 *          hierarchy.
3719 */
3720static xmlElementContentPtr
3721xmlOldParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
3722    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
3723    xmlChar *elem;
3724    xmlChar type = 0;
3725
3726    SKIP_BLANKS;
3727    GROW;
3728    if (CUR == '(') {
3729        /* Recurse on first child */
3730        NEXT;
3731        SKIP_BLANKS;
3732        cur = ret = xmlOldParseElementChildrenContentDecl(ctxt);
3733        SKIP_BLANKS;
3734        GROW;
3735    } else {
3736        elem = xmlOldParseName(ctxt);
3737        if (elem == NULL) {
3738            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3739                ctxt->sax->error(ctxt->userData,
3740                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
3741            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3742            ctxt->wellFormed = 0;
3743            return(NULL);
3744        }
3745        cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3746        GROW;
3747        if (CUR == '?') {
3748            cur->ocur = XML_ELEMENT_CONTENT_OPT;
3749            NEXT;
3750        } else if (CUR == '*') {
3751            cur->ocur = XML_ELEMENT_CONTENT_MULT;
3752            NEXT;
3753        } else if (CUR == '+') {
3754            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
3755            NEXT;
3756        } else {
3757            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
3758        }
3759        xmlFree(elem);
3760        GROW;
3761    }
3762    SKIP_BLANKS;
3763    SHRINK;
3764    while (CUR != ')') {
3765        /*
3766         * Each loop we parse one separator and one element.
3767         */
3768        if (CUR == ',') {
3769            if (type == 0) type = CUR;
3770
3771            /*
3772             * Detect "Name | Name , Name" error
3773             */
3774            else if (type != CUR) {
3775                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3776                    ctxt->sax->error(ctxt->userData,
3777                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
3778                    type);
3779                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
3780                ctxt->wellFormed = 0;
3781                xmlFreeElementContent(ret);
3782                return(NULL);
3783            }
3784            NEXT;
3785
3786            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
3787            if (op == NULL) {
3788                xmlFreeElementContent(ret);
3789                return(NULL);
3790            }
3791            if (last == NULL) {
3792                op->c1 = ret;
3793                ret = cur = op;
3794            } else {
3795                cur->c2 = op;
3796                op->c1 = last;
3797                cur =op;
3798                last = NULL;
3799            }
3800        } else if (CUR == '|') {
3801            if (type == 0) type = CUR;
3802
3803            /*
3804             * Detect "Name , Name | Name" error
3805             */
3806            else if (type != CUR) {
3807                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3808                    ctxt->sax->error(ctxt->userData,
3809                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
3810                    type);
3811                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
3812                ctxt->wellFormed = 0;
3813                xmlFreeElementContent(ret);
3814                return(NULL);
3815            }
3816            NEXT;
3817
3818            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3819            if (op == NULL) {
3820                xmlFreeElementContent(ret);
3821                return(NULL);
3822            }
3823            if (last == NULL) {
3824                op->c1 = ret;
3825                ret = cur = op;
3826            } else {
3827                cur->c2 = op;
3828                op->c1 = last;
3829                cur =op;
3830                last = NULL;
3831            }
3832        } else {
3833            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3834                ctxt->sax->error(ctxt->userData,
3835            "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
3836            ctxt->wellFormed = 0;
3837            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
3838            xmlFreeElementContent(ret);
3839            return(NULL);
3840        }
3841        GROW;
3842        SKIP_BLANKS;
3843        GROW;
3844        if (CUR == '(') {
3845            /* Recurse on second child */
3846            NEXT;
3847            SKIP_BLANKS;
3848            last = xmlOldParseElementChildrenContentDecl(ctxt);
3849            SKIP_BLANKS;
3850        } else {
3851            elem = xmlOldParseName(ctxt);
3852            if (elem == NULL) {
3853                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3854                    ctxt->sax->error(ctxt->userData,
3855                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
3856                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3857                ctxt->wellFormed = 0;
3858                return(NULL);
3859            }
3860            last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3861            xmlFree(elem);
3862            if (CUR == '?') {
3863                last->ocur = XML_ELEMENT_CONTENT_OPT;
3864                NEXT;
3865            } else if (CUR == '*') {
3866                last->ocur = XML_ELEMENT_CONTENT_MULT;
3867                NEXT;
3868            } else if (CUR == '+') {
3869                last->ocur = XML_ELEMENT_CONTENT_PLUS;
3870                NEXT;
3871            } else {
3872                last->ocur = XML_ELEMENT_CONTENT_ONCE;
3873            }
3874        }
3875        SKIP_BLANKS;
3876        GROW;
3877    }
3878    if ((cur != NULL) && (last != NULL)) {
3879        cur->c2 = last;
3880    }
3881    NEXT;
3882    if (CUR == '?') {
3883        ret->ocur = XML_ELEMENT_CONTENT_OPT;
3884        NEXT;
3885    } else if (CUR == '*') {
3886        ret->ocur = XML_ELEMENT_CONTENT_MULT;
3887        NEXT;
3888    } else if (CUR == '+') {
3889        ret->ocur = XML_ELEMENT_CONTENT_PLUS;
3890        NEXT;
3891    }
3892    return(ret);
3893}
3894
3895/**
3896 * xmlOldParseElementContentDecl:
3897 * @ctxt:  an XML parser context
3898 * @name:  the name of the element being defined.
3899 * @result:  the Element Content pointer will be stored here if any
3900 *
3901 * parse the declaration for an Element content either Mixed or Children,
3902 * the cases EMPTY and ANY are handled directly in xmlOldParseElementDecl
3903 *
3904 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
3905 *
3906 * returns: the type of element content XML_ELEMENT_TYPE_xxx
3907 */
3908
3909static int
3910xmlOldParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
3911                           xmlElementContentPtr *result) {
3912
3913    xmlElementContentPtr tree = NULL;
3914    int res;
3915
3916    *result = NULL;
3917
3918    if (CUR != '(') {
3919        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3920            ctxt->sax->error(ctxt->userData,
3921                "xmlParseElementContentDecl : '(' expected\n");
3922        ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
3923        ctxt->wellFormed = 0;
3924        return(-1);
3925    }
3926    NEXT;
3927    GROW;
3928    SKIP_BLANKS;
3929    if ((CUR == '#') && (NXT(1) == 'P') &&
3930        (NXT(2) == 'C') && (NXT(3) == 'D') &&
3931        (NXT(4) == 'A') && (NXT(5) == 'T') &&
3932        (NXT(6) == 'A')) {
3933        tree = xmlOldParseElementMixedContentDecl(ctxt);
3934        res = XML_ELEMENT_TYPE_MIXED;
3935    } else {
3936        tree = xmlOldParseElementChildrenContentDecl(ctxt);
3937        res = XML_ELEMENT_TYPE_ELEMENT;
3938    }
3939    SKIP_BLANKS;
3940    /****************************
3941    if (CUR != ')') {
3942        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3943            ctxt->sax->error(ctxt->userData,
3944                "xmlParseElementContentDecl : ')' expected\n");
3945        ctxt->wellFormed = 0;
3946        return(-1);
3947    }
3948     ****************************/
3949    *result = tree;
3950    return(res);
3951}
3952
3953/**
3954 * xmlOldParseElementDecl:
3955 * @ctxt:  an XML parser context
3956 *
3957 * parse an Element declaration.
3958 *
3959 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
3960 *
3961 * [ VC: Unique Element Type Declaration ]
3962 * No element type may be declared more than once
3963 *
3964 * Returns the type of the element, or -1 in case of error
3965 */
3966static int
3967xmlOldParseElementDecl(xmlParserCtxtPtr ctxt) {
3968    xmlChar *name;
3969    int ret = -1;
3970    xmlElementContentPtr content  = NULL;
3971
3972    GROW;
3973    if ((CUR == '<') && (NXT(1) == '!') &&
3974        (NXT(2) == 'E') && (NXT(3) == 'L') &&
3975        (NXT(4) == 'E') && (NXT(5) == 'M') &&
3976        (NXT(6) == 'E') && (NXT(7) == 'N') &&
3977        (NXT(8) == 'T')) {
3978        SKIP(9);
3979        if (!IS_BLANK(CUR)) {
3980            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3981                ctxt->sax->error(ctxt->userData,
3982                    "Space required after 'ELEMENT'\n");
3983            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
3984            ctxt->wellFormed = 0;
3985        }
3986        SKIP_BLANKS;
3987        name = xmlOldParseName(ctxt);
3988        if (name == NULL) {
3989            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3990                ctxt->sax->error(ctxt->userData,
3991                   "xmlParseElementDecl: no name for Element\n");
3992            ctxt->errNo = XML_ERR_NAME_REQUIRED;
3993            ctxt->wellFormed = 0;
3994            return(-1);
3995        }
3996        if (!IS_BLANK(CUR)) {
3997            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3998                ctxt->sax->error(ctxt->userData,
3999                    "Space required after the element name\n");
4000            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4001            ctxt->wellFormed = 0;
4002        }
4003        SKIP_BLANKS;
4004        if ((CUR == 'E') && (NXT(1) == 'M') &&
4005            (NXT(2) == 'P') && (NXT(3) == 'T') &&
4006            (NXT(4) == 'Y')) {
4007            SKIP(5);
4008            /*
4009             * Element must always be empty.
4010             */
4011            ret = XML_ELEMENT_TYPE_EMPTY;
4012        } else if ((CUR == 'A') && (NXT(1) == 'N') &&
4013                   (NXT(2) == 'Y')) {
4014            SKIP(3);
4015            /*
4016             * Element is a generic container.
4017             */
4018            ret = XML_ELEMENT_TYPE_ANY;
4019        } else if (CUR == '(') {
4020            ret = xmlOldParseElementContentDecl(ctxt, name, &content);
4021        } else {
4022            /*
4023             * [ WFC: PEs in Internal Subset ] error handling.
4024             */
4025            if ((CUR == '%') && (ctxt->external == 0) &&
4026                (ctxt->inputNr == 1)) {
4027                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4028                    ctxt->sax->error(ctxt->userData,
4029          "PEReference: forbidden within markup decl in internal subset\n");
4030                ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
4031            } else {
4032                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4033                    ctxt->sax->error(ctxt->userData,
4034                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
4035                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
4036            }
4037            ctxt->wellFormed = 0;
4038            if (name != NULL) xmlFree(name);
4039            return(-1);
4040        }
4041
4042        SKIP_BLANKS;
4043        /*
4044         * Pop-up of finished entities.
4045         */
4046        while ((CUR == 0) && (ctxt->inputNr > 1))
4047            xmlOldPopInput(ctxt);
4048        SKIP_BLANKS;
4049
4050        if (CUR != '>') {
4051            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4052                ctxt->sax->error(ctxt->userData,
4053                  "xmlParseElementDecl: expected '>' at the end\n");
4054            ctxt->errNo = XML_ERR_GT_REQUIRED;
4055            ctxt->wellFormed = 0;
4056        } else {
4057            NEXT;
4058            if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
4059                ctxt->sax->elementDecl(ctxt->userData, name, ret,
4060                                       content);
4061        }
4062        if (content != NULL) {
4063            xmlFreeElementContent(content);
4064        }
4065        if (name != NULL) {
4066            xmlFree(name);
4067        }
4068    }
4069    return(ret);
4070}
4071
4072/**
4073 * xmlOldParseMarkupDecl:
4074 * @ctxt:  an XML parser context
4075 *
4076 * parse Markup declarations
4077 *
4078 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
4079 *                     NotationDecl | PI | Comment
4080 *
4081 * [ VC: Proper Declaration/PE Nesting ]
4082 * TODO Parameter-entity replacement text must be properly nested with
4083 * markup declarations. That is to say, if either the first character
4084 * or the last character of a markup declaration (markupdecl above) is
4085 * contained in the replacement text for a parameter-entity reference,
4086 * both must be contained in the same replacement text.
4087 *
4088 * [ WFC: PEs in Internal Subset ]
4089 * In the internal DTD subset, parameter-entity references can occur
4090 * only where markup declarations can occur, not within markup declarations.
4091 * (This does not apply to references that occur in external parameter
4092 * entities or to the external subset.)
4093 */
4094static void
4095xmlOldParseMarkupDecl(xmlParserCtxtPtr ctxt) {
4096    GROW;
4097    xmlOldParseElementDecl(ctxt);
4098    xmlOldParseAttributeListDecl(ctxt);
4099    xmlOldParseEntityDecl(ctxt);
4100    xmlOldParseNotationDecl(ctxt);
4101    xmlOldParsePI(ctxt);
4102    xmlOldParseComment(ctxt);
4103    /*
4104     * This is only for internal subset. On external entities,
4105     * the replacement is done before parsing stage
4106     */
4107    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
4108        xmlOldParsePEReference(ctxt);
4109    ctxt->instate = XML_PARSER_DTD;
4110}
4111
4112/**
4113 * xmlOldParseTextDecl:
4114 * @ctxt:  an XML parser context
4115 *
4116 * parse an XML declaration header for external entities
4117 *
4118 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
4119 *
4120 * Returns the only valuable info for an external parsed entity, the encoding
4121 */
4122
4123static xmlChar *
4124xmlOldParseTextDecl(xmlParserCtxtPtr ctxt) {
4125    xmlChar *version;
4126    xmlChar *encoding = NULL;
4127
4128    /*
4129     * We know that '<?xml' is here.
4130     */
4131    SKIP(5);
4132
4133    if (!IS_BLANK(CUR)) {
4134        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4135            ctxt->sax->error(ctxt->userData,
4136                             "Space needed after '<?xml'\n");
4137        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4138        ctxt->wellFormed = 0;
4139    }
4140    SKIP_BLANKS;
4141
4142    /*
4143     * We may have the VersionInfo here.
4144     */
4145    version = xmlOldParseVersionInfo(ctxt);
4146    if (version == NULL)
4147        version = xmlCharStrdup(XML_DEFAULT_VERSION);
4148    ctxt->version = xmlStrdup(version);
4149    xmlFree(version);
4150
4151    /*
4152     * We must have the encoding declaration
4153     */
4154    if (!IS_BLANK(CUR)) {
4155        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4156            ctxt->sax->error(ctxt->userData, "Space needed here\n");
4157        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
4158        ctxt->wellFormed = 0;
4159    }
4160    encoding = xmlOldParseEncodingDecl(ctxt);
4161
4162    SKIP_BLANKS;
4163    if ((CUR == '?') && (NXT(1) == '>')) {
4164        SKIP(2);
4165    } else if (CUR == '>') {
4166        /* Deprecated old WD ... */
4167        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4168            ctxt->sax->error(ctxt->userData,
4169                             "XML declaration must end-up with '?>'\n");
4170        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
4171        ctxt->wellFormed = 0;
4172        NEXT;
4173    } else {
4174        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4175            ctxt->sax->error(ctxt->userData,
4176                             "parsing XML declaration: '?>' expected\n");
4177        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
4178        ctxt->wellFormed = 0;
4179        MOVETO_ENDTAG(CUR_PTR);
4180        NEXT;
4181    }
4182    return(encoding);
4183}
4184
4185/*
4186 * xmlOldParseConditionalSections
4187 * @ctxt:  an XML parser context
4188 *
4189 * TODO : Conditionnal section are not yet supported !
4190 *
4191 * [61] conditionalSect ::= includeSect | ignoreSect
4192 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
4193 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
4194 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
4195 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
4196 */
4197
4198static void
4199xmlOldParseConditionalSections(xmlParserCtxtPtr ctxt) {
4200    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4201        ctxt->sax->warning(ctxt->userData,
4202                           "XML conditional section not supported\n");
4203    /*
4204     * Skip up to the end of the conditionnal section.
4205     */
4206    while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>'))) {
4207        NEXT;
4208        /*
4209         * Pop-up of finished entities.
4210         */
4211        while ((CUR == 0) && (ctxt->inputNr > 1))
4212            xmlOldPopInput(ctxt);
4213
4214        if (CUR == 0)
4215            GROW;
4216    }
4217
4218    if (CUR == 0)
4219        SHRINK;
4220
4221    if (CUR == 0) {
4222        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4223            ctxt->sax->error(ctxt->userData,
4224                "XML conditional section not closed\n");
4225        ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
4226        ctxt->wellFormed = 0;
4227    } else {
4228        SKIP(3);
4229    }
4230}
4231
4232/**
4233 * xmlOldParseExternalSubset:
4234 * @ctxt:  an XML parser context
4235 * @ExternalID: the external identifier
4236 * @SystemID: the system identifier (or URL)
4237 *
4238 * parse Markup declarations from an external subset
4239 *
4240 * [30] extSubset ::= textDecl? extSubsetDecl
4241 *
4242 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
4243 */
4244void
4245xmlOldParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
4246                       const xmlChar *SystemID) {
4247    GROW;
4248    if ((CUR == '<') && (NXT(1) == '?') &&
4249        (NXT(2) == 'x') && (NXT(3) == 'm') &&
4250        (NXT(4) == 'l')) {
4251        xmlChar *decl;
4252
4253        decl = xmlOldParseTextDecl(ctxt);
4254        if (decl != NULL)
4255            xmlFree(decl);
4256    }
4257    if (ctxt->myDoc == NULL) {
4258        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
4259    }
4260    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
4261        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
4262
4263    ctxt->instate = XML_PARSER_DTD;
4264    ctxt->external = 1;
4265    while (((CUR == '<') && (NXT(1) == '?')) ||
4266           ((CUR == '<') && (NXT(1) == '!')) ||
4267           IS_BLANK(CUR)) {
4268        const xmlChar *check = CUR_PTR;
4269        int cons = ctxt->input->consumed;
4270
4271        if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4272            xmlOldParseConditionalSections(ctxt);
4273        } else if (IS_BLANK(CUR)) {
4274            NEXT;
4275        } else if (CUR == '%') {
4276            xmlOldParsePEReference(ctxt);
4277        } else
4278            xmlOldParseMarkupDecl(ctxt);
4279
4280        /*
4281         * Pop-up of finished entities.
4282         */
4283        while ((CUR == 0) && (ctxt->inputNr > 1))
4284            xmlOldPopInput(ctxt);
4285
4286        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
4287            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4288                ctxt->sax->error(ctxt->userData,
4289                    "Content error in the external subset\n");
4290            ctxt->wellFormed = 0;
4291            ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
4292            break;
4293        }
4294    }
4295   
4296    if (CUR != 0) {
4297        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4298            ctxt->sax->error(ctxt->userData,
4299                "Extra content at the end of the document\n");
4300        ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
4301        ctxt->wellFormed = 0;
4302    }
4303
4304}
4305
4306/**
4307 * xmlOldParseReference:
4308 * @ctxt:  an XML parser context
4309 *
4310 * parse and handle entity references in content, depending on the SAX
4311 * interface, this may end-up in a call to character() if this is a
4312 * CharRef, a predefined entity, if there is no reference() callback.
4313 * or if the parser was asked to switch to that mode.
4314 *
4315 * [67] Reference ::= EntityRef | CharRef
4316 */
4317static void
4318xmlOldParseReference(xmlParserCtxtPtr ctxt) {
4319    xmlEntityPtr ent;
4320    xmlChar *val;
4321    if (CUR != '&') return;
4322#if 0
4323    if (ctxt->inputNr > 1) {
4324        xmlChar cur[2] = { '&' , 0 } ;
4325
4326        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4327            ctxt->sax->characters(ctxt->userData, cur, 1);
4328        if (ctxt->token == '&')
4329            ctxt->token = 0;
4330        else {
4331            SKIP(1);
4332        }
4333        return;
4334    }
4335#endif
4336    if (NXT(1) == '#') {
4337        xmlChar out[2];
4338        int val = xmlOldParseCharRef(ctxt);
4339        /* invalid for UTF-8 variable encoding !!!!! */
4340        out[0] = val;
4341        out[1] = 0;
4342        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4343            ctxt->sax->characters(ctxt->userData, out, 1);
4344    } else {
4345        ent = xmlOldParseEntityRef(ctxt);
4346        if (ent == NULL) return;
4347        if ((ent->name != NULL) &&
4348            (ent->type != XML_INTERNAL_PREDEFINED_ENTITY)) {
4349            if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
4350                (ctxt->replaceEntities == 0)) {
4351                /*
4352                 * Create a node.
4353                 */
4354                ctxt->sax->reference(ctxt->userData, ent->name);
4355                return;
4356            } else if (ctxt->replaceEntities) {
4357                xmlParserInputPtr input;
4358
4359                input = xmlOldNewEntityInputStream(ctxt, ent);
4360                xmlOldPushInput(ctxt, input);
4361                return;
4362            }
4363        }
4364        val = ent->content;
4365        if (val == NULL) return;
4366        /*
4367         * inline the entity.
4368         */
4369        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4370            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
4371    }
4372}
4373
4374/**
4375 * xmlOldParseEntityRef:
4376 * @ctxt:  an XML parser context
4377 *
4378 * parse ENTITY references declarations
4379 *
4380 * [68] EntityRef ::= '&' Name ';'
4381 *
4382 * [ WFC: Entity Declared ]
4383 * In a document without any DTD, a document with only an internal DTD
4384 * subset which contains no parameter entity references, or a document
4385 * with "standalone='yes'", the Name given in the entity reference
4386 * must match that in an entity declaration, except that well-formed
4387 * documents need not declare any of the following entities: amp, lt,
4388 * gt, apos, quot.  The declaration of a parameter entity must precede
4389 * any reference to it.  Similarly, the declaration of a general entity
4390 * must precede any reference to it which appears in a default value in an
4391 * attribute-list declaration. Note that if entities are declared in the
4392 * external subset or in external parameter entities, a non-validating
4393 * processor is not obligated to read and process their declarations;
4394 * for such documents, the rule that an entity must be declared is a
4395 * well-formedness constraint only if standalone='yes'.
4396 *
4397 * [ WFC: Parsed Entity ]
4398 * An entity reference must not contain the name of an unparsed entity
4399 *
4400 * Returns the xmlEntityPtr if found, or NULL otherwise.
4401 */
4402static xmlEntityPtr
4403xmlOldParseEntityRef(xmlParserCtxtPtr ctxt) {
4404    xmlChar *name;
4405    xmlEntityPtr ent = NULL;
4406
4407    GROW;
4408   
4409    if (CUR == '&') {
4410        NEXT;
4411        name = xmlOldParseName(ctxt);
4412        if (name == NULL) {
4413            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4414                ctxt->sax->error(ctxt->userData,
4415                                 "xmlParseEntityRef: no name\n");
4416            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4417            ctxt->wellFormed = 0;
4418        } else {
4419            if (CUR == ';') {
4420                NEXT;
4421                /*
4422                 * Ask first SAX for entity resolution, otherwise try the
4423                 * predefined set.
4424                 */
4425                if (ctxt->sax != NULL) {
4426                    if (ctxt->sax->getEntity != NULL)
4427                        ent = ctxt->sax->getEntity(ctxt->userData, name);
4428                    if (ent == NULL)
4429                        ent = xmlGetPredefinedEntity(name);
4430                }
4431                /*
4432                 * [ WFC: Entity Declared ]
4433                 * In a document without any DTD, a document with only an
4434                 * internal DTD subset which contains no parameter entity
4435                 * references, or a document with "standalone='yes'", the
4436                 * Name given in the entity reference must match that in an
4437                 * entity declaration, except that well-formed documents
4438                 * need not declare any of the following entities: amp, lt,
4439                 * gt, apos, quot.
4440                 * The declaration of a parameter entity must precede any
4441                 * reference to it.
4442                 * Similarly, the declaration of a general entity must
4443                 * precede any reference to it which appears in a default
4444                 * value in an attribute-list declaration. Note that if
4445                 * entities are declared in the external subset or in
4446                 * external parameter entities, a non-validating processor
4447                 * is not obligated to read and process their declarations;
4448                 * for such documents, the rule that an entity must be
4449                 * declared is a well-formedness constraint only if
4450                 * standalone='yes'.
4451                 */
4452                if (ent == NULL) {
4453                    if ((ctxt->standalone == 1) ||
4454                        ((ctxt->hasExternalSubset == 0) &&
4455                         (ctxt->hasPErefs == 0))) {
4456                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4457                            ctxt->sax->error(ctxt->userData,
4458                                 "Entity '%s' not defined\n", name);
4459                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4460                        ctxt->wellFormed = 0;
4461                    } else {
4462                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4463                            ctxt->sax->warning(ctxt->userData,
4464                                 "Entity '%s' not defined\n", name);
4465                        ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
4466                    }
4467                }
4468
4469                /*
4470                 * [ WFC: Parsed Entity ]
4471                 * An entity reference must not contain the name of an
4472                 * unparsed entity
4473                 */
4474                else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4475                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4476                        ctxt->sax->error(ctxt->userData,
4477                             "Entity reference to unparsed entity %s\n", name);
4478                    ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
4479                    ctxt->wellFormed = 0;
4480                }
4481
4482                /*
4483                 * [ WFC: No External Entity References ]
4484                 * Attribute values cannot contain direct or indirect
4485                 * entity references to external entities.
4486                 */
4487                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4488                         (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4489                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4490                        ctxt->sax->error(ctxt->userData,
4491                     "Attribute references external entity '%s'\n", name);
4492                    ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
4493                    ctxt->wellFormed = 0;
4494                }
4495                /*
4496                 * [ WFC: No < in Attribute Values ]
4497                 * The replacement text of any entity referred to directly or
4498                 * indirectly in an attribute value (other than "&lt;") must
4499                 * not contain a <.
4500                 */
4501                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4502                         (ent != NULL) &&
4503                         (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
4504                         (ent->content != NULL) &&
4505                         (xmlStrchr(ent->content, '<'))) {
4506                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4507                        ctxt->sax->error(ctxt->userData,
4508         "'<' in entity '%s' is not allowed in attributes values\n", name);
4509                    ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
4510                    ctxt->wellFormed = 0;
4511                }
4512
4513                /*
4514                 * Internal check, no parameter entities here ...
4515                 */
4516                else {
4517                    switch (ent->type) {
4518                        case XML_INTERNAL_PARAMETER_ENTITY:
4519                        case XML_EXTERNAL_PARAMETER_ENTITY:
4520                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4521                            ctxt->sax->error(ctxt->userData,
4522                     "Attempt to reference the parameter entity '%s'\n", name);
4523                        ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
4524                        ctxt->wellFormed = 0;
4525                        break;
4526                    }
4527                }
4528
4529                /*
4530                 * [ WFC: No Recursion ]
4531                 * TODO A parsed entity must not contain a recursive reference
4532                 * to itself, either directly or indirectly.
4533                 */
4534
4535            } else {
4536                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4537                    ctxt->sax->error(ctxt->userData,
4538                                     "xmlParseEntityRef: expecting ';'\n");
4539                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4540                ctxt->wellFormed = 0;
4541            }
4542            xmlFree(name);
4543        }
4544    }
4545    return(ent);
4546}
4547/**
4548 * xmlOldParseStringEntityRef:
4549 * @ctxt:  an XML parser context
4550 * @str:  a pointer to an index in the string
4551 *
4552 * parse ENTITY references declarations, but this version parses it from
4553 * a string value.
4554 *
4555 * [68] EntityRef ::= '&' Name ';'
4556 *
4557 * [ WFC: Entity Declared ]
4558 * In a document without any DTD, a document with only an internal DTD
4559 * subset which contains no parameter entity references, or a document
4560 * with "standalone='yes'", the Name given in the entity reference
4561 * must match that in an entity declaration, except that well-formed
4562 * documents need not declare any of the following entities: amp, lt,
4563 * gt, apos, quot.  The declaration of a parameter entity must precede
4564 * any reference to it.  Similarly, the declaration of a general entity
4565 * must precede any reference to it which appears in a default value in an
4566 * attribute-list declaration. Note that if entities are declared in the
4567 * external subset or in external parameter entities, a non-validating
4568 * processor is not obligated to read and process their declarations;
4569 * for such documents, the rule that an entity must be declared is a
4570 * well-formedness constraint only if standalone='yes'.
4571 *
4572 * [ WFC: Parsed Entity ]
4573 * An entity reference must not contain the name of an unparsed entity
4574 *
4575 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
4576 * is updated to the current location in the string.
4577 */
4578static xmlEntityPtr
4579xmlOldParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
4580    xmlChar *name;
4581    const xmlChar *ptr;
4582    xmlChar cur;
4583    xmlEntityPtr ent = NULL;
4584
4585    GROW;
4586   
4587    if ((str == NULL) || (*str == NULL)) return(NULL); /* !!! */
4588    ptr = *str;
4589    cur = *ptr;
4590    if (cur == '&') {
4591        ptr++;
4592        cur = *ptr;
4593        name = xmlOldParseStringName(ctxt, &ptr);
4594        if (name == NULL) {
4595            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4596                ctxt->sax->error(ctxt->userData,
4597                                 "xmlParseEntityRef: no name\n");
4598            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4599            ctxt->wellFormed = 0;
4600        } else {
4601            if (CUR == ';') {
4602                NEXT;
4603                /*
4604                 * Ask first SAX for entity resolution, otherwise try the
4605                 * predefined set.
4606                 */
4607                if (ctxt->sax != NULL) {
4608                    if (ctxt->sax->getEntity != NULL)
4609                        ent = ctxt->sax->getEntity(ctxt->userData, name);
4610                    if (ent == NULL)
4611                        ent = xmlGetPredefinedEntity(name);
4612                }
4613                /*
4614                 * [ WFC: Entity Declared ]
4615                 * In a document without any DTD, a document with only an
4616                 * internal DTD subset which contains no parameter entity
4617                 * references, or a document with "standalone='yes'", the
4618                 * Name given in the entity reference must match that in an
4619                 * entity declaration, except that well-formed documents
4620                 * need not declare any of the following entities: amp, lt,
4621                 * gt, apos, quot.
4622                 * The declaration of a parameter entity must precede any
4623                 * reference to it.
4624                 * Similarly, the declaration of a general entity must
4625                 * precede any reference to it which appears in a default
4626                 * value in an attribute-list declaration. Note that if
4627                 * entities are declared in the external subset or in
4628                 * external parameter entities, a non-validating processor
4629                 * is not obligated to read and process their declarations;
4630                 * for such documents, the rule that an entity must be
4631                 * declared is a well-formedness constraint only if
4632                 * standalone='yes'.
4633                 */
4634                if (ent == NULL) {
4635                    if ((ctxt->standalone == 1) ||
4636                        ((ctxt->hasExternalSubset == 0) &&
4637                         (ctxt->hasPErefs == 0))) {
4638                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4639                            ctxt->sax->error(ctxt->userData,
4640                                 "Entity '%s' not defined\n", name);
4641                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4642                        ctxt->wellFormed = 0;
4643                    } else {
4644                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4645                            ctxt->sax->warning(ctxt->userData,
4646                                 "Entity '%s' not defined\n", name);
4647                        ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
4648                    }
4649                }
4650
4651                /*
4652                 * [ WFC: Parsed Entity ]
4653                 * An entity reference must not contain the name of an
4654                 * unparsed entity
4655                 */
4656                else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4657                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4658                        ctxt->sax->error(ctxt->userData,
4659                             "Entity reference to unparsed entity %s\n", name);
4660                    ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
4661                    ctxt->wellFormed = 0;
4662                }
4663
4664                /*
4665                 * [ WFC: No External Entity References ]
4666                 * Attribute values cannot contain direct or indirect
4667                 * entity references to external entities.
4668                 */
4669                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4670                         (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4671                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4672                        ctxt->sax->error(ctxt->userData,
4673                     "Attribute references external entity '%s'\n", name);
4674                    ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
4675                    ctxt->wellFormed = 0;
4676                }
4677                /*
4678                 * [ WFC: No < in Attribute Values ]
4679                 * The replacement text of any entity referred to directly or
4680                 * indirectly in an attribute value (other than "&lt;") must
4681                 * not contain a <.
4682                 */
4683                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4684                         (ent != NULL) &&
4685                         (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
4686                         (ent->content != NULL) &&
4687                         (xmlStrchr(ent->content, '<'))) {
4688                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4689                        ctxt->sax->error(ctxt->userData,
4690         "'<' in entity '%s' is not allowed in attributes values\n", name);
4691                    ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
4692                    ctxt->wellFormed = 0;
4693                }
4694
4695                /*
4696                 * Internal check, no parameter entities here ...
4697                 */
4698                else {
4699                    switch (ent->type) {
4700                        case XML_INTERNAL_PARAMETER_ENTITY:
4701                        case XML_EXTERNAL_PARAMETER_ENTITY:
4702                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4703                            ctxt->sax->error(ctxt->userData,
4704                     "Attempt to reference the parameter entity '%s'\n", name);
4705                        ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
4706                        ctxt->wellFormed = 0;
4707                        break;
4708                    }
4709                }
4710
4711                /*
4712                 * [ WFC: No Recursion ]
4713                 * TODO A parsed entity must not contain a recursive reference
4714                 * to itself, either directly or indirectly.
4715                 */
4716
4717            } else {
4718                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4719                    ctxt->sax->error(ctxt->userData,
4720                                     "xmlParseEntityRef: expecting ';'\n");
4721                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4722                ctxt->wellFormed = 0;
4723            }
4724            xmlFree(name);
4725        }
4726    }
4727    return(ent);
4728}
4729
4730/**
4731 * xmlOldParsePEReference:
4732 * @ctxt:  an XML parser context
4733 *
4734 * parse PEReference declarations
4735 * The entity content is handled directly by pushing it's content as
4736 * a new input stream.
4737 *
4738 * [69] PEReference ::= '%' Name ';'
4739 *
4740 * [ WFC: No Recursion ]
4741 * TODO A parsed entity must not contain a recursive
4742 * reference to itself, either directly or indirectly.
4743 *
4744 * [ WFC: Entity Declared ]
4745 * In a document without any DTD, a document with only an internal DTD
4746 * subset which contains no parameter entity references, or a document
4747 * with "standalone='yes'", ...  ... The declaration of a parameter
4748 * entity must precede any reference to it...
4749 *
4750 * [ VC: Entity Declared ]
4751 * In a document with an external subset or external parameter entities
4752 * with "standalone='no'", ...  ... The declaration of a parameter entity
4753 * must precede any reference to it...
4754 *
4755 * [ WFC: In DTD ]
4756 * Parameter-entity references may only appear in the DTD.
4757 * NOTE: misleading but this is handled.
4758 */
4759static void
4760xmlOldParsePEReference(xmlParserCtxtPtr ctxt) {
4761    xmlChar *name;
4762    xmlEntityPtr entity = NULL;
4763    xmlParserInputPtr input;
4764
4765    if (CUR == '%') {
4766        NEXT;
4767        name = xmlOldParseName(ctxt);
4768        if (name == NULL) {
4769            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4770                ctxt->sax->error(ctxt->userData,
4771                                 "xmlParsePEReference: no name\n");
4772            ctxt->errNo = XML_ERR_NAME_REQUIRED;
4773            ctxt->wellFormed = 0;
4774        } else {
4775            if (CUR == ';') {
4776                NEXT;
4777                if ((ctxt->sax != NULL) &&
4778                    (ctxt->sax->getParameterEntity != NULL))
4779                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
4780                                                           name);
4781                if (entity == NULL) {
4782                    /*
4783                     * [ WFC: Entity Declared ]
4784                     * In a document without any DTD, a document with only an
4785                     * internal DTD subset which contains no parameter entity
4786                     * references, or a document with "standalone='yes'", ...
4787                     * ... The declaration of a parameter entity must precede
4788                     * any reference to it...
4789                     */
4790                    if ((ctxt->standalone == 1) ||
4791                        ((ctxt->hasExternalSubset == 0) &&
4792                         (ctxt->hasPErefs == 0))) {
4793                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4794                            ctxt->sax->error(ctxt->userData,
4795                             "PEReference: %%%s; not found\n", name);
4796                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
4797                        ctxt->wellFormed = 0;
4798                    } else {
4799                        /*
4800                         * [ VC: Entity Declared ]
4801                         * In a document with an external subset or external
4802                         * parameter entities with "standalone='no'", ...
4803                         * ... The declaration of a parameter entity must precede
4804                         * any reference to it...
4805                         */
4806                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4807                            ctxt->sax->warning(ctxt->userData,
4808                             "PEReference: %%%s; not found\n", name);
4809                        ctxt->valid = 0;
4810                    }
4811                } else {
4812                    /*
4813                     * Internal checking in case the entity quest barfed
4814                     */
4815                    if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
4816                        (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
4817                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4818                            ctxt->sax->warning(ctxt->userData,
4819                         "Internal: %%%s; is not a parameter entity\n", name);
4820                    } else {
4821                        input = xmlOldNewEntityInputStream(ctxt, entity);
4822                        xmlOldPushInput(ctxt, input);
4823                    }
4824                }
4825                ctxt->hasPErefs = 1;
4826            } else {
4827                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4828                    ctxt->sax->error(ctxt->userData,
4829                                     "xmlParsePEReference: expecting ';'\n");
4830                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
4831                ctxt->wellFormed = 0;
4832            }
4833            xmlFree(name);
4834        }
4835    }
4836}
4837
4838/**
4839 * xmlOldParseStringPEReference:
4840 * @ctxt:  an XML parser context
4841 * @str:  a pointer to an index in the string
4842 *
4843 * parse PEReference declarations
4844 *
4845 * [69] PEReference ::= '%' Name ';'
4846 *
4847 * [ WFC: No Recursion ]
4848 * TODO A parsed entity must not contain a recursive
4849 * reference to itself, either directly or indirectly.
4850 *
4851 * [ WFC: Entity Declared ]
4852 * In a document without any DTD, a document with only an internal DTD
4853 *