blob: 83151fe6d2e635b4fab3b0da2294967c314f3dee [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * parser.c : an XML 1.0 non-verifying parser
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
9#ifdef WIN32
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000014#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000015
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000017#include <string.h> /* for memset() only */
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
Seth Alvese7f12e61998-10-01 20:51:15 +000022#include <stdlib.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000023#endif
24#ifdef HAVE_SYS_STAT_H
Daniel Veillard260a68f1998-08-13 03:39:55 +000025#include <sys/stat.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000026#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000027#ifdef HAVE_FCNTL_H
28#include <fcntl.h>
29#endif
30#ifdef HAVE_UNISTD_H
31#include <unistd.h>
32#endif
33#ifdef HAVE_ZLIB_H
34#include <zlib.h>
35#endif
36
Daniel Veillard6454aec1999-09-02 22:04:43 +000037#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000038#include "tree.h"
39#include "parser.h"
40#include "entities.h"
Daniel Veillard27d88741999-05-29 11:51:49 +000041#include "encoding.h"
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000042#include "valid.h"
Daniel Veillard1e346af1999-02-22 10:33:01 +000043#include "parserInternals.h"
Daniel Veillarde2d034d1999-07-27 19:52:06 +000044#include "xmlIO.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000045#include "xml-error.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000046
Daniel Veillard14fff061999-06-22 21:49:07 +000047const char *xmlParserVersion = LIBXML_VERSION;
48
Daniel Veillarde2d034d1999-07-27 19:52:06 +000049
50/************************************************************************
51 * *
52 * Input handling functions for progressive parsing *
53 * *
54 ************************************************************************/
55
56/* #define DEBUG_INPUT */
57
Daniel Veillardb05deb71999-08-10 19:04:08 +000058#define INPUT_CHUNK 250
59/* we need to keep enough input to show errors in context */
60#define LINE_LEN 80
Daniel Veillarde2d034d1999-07-27 19:52:06 +000061
62#ifdef DEBUG_INPUT
63#define CHECK_BUFFER(in) check_buffer(in)
Daniel Veillarde2d034d1999-07-27 19:52:06 +000064
65void check_buffer(xmlParserInputPtr in) {
66 if (in->base != in->buf->buffer->content) {
67 fprintf(stderr, "xmlParserInput: base mismatch problem\n");
68 }
69 if (in->cur < in->base) {
70 fprintf(stderr, "xmlParserInput: cur < base problem\n");
71 }
72 if (in->cur > in->base + in->buf->buffer->use) {
73 fprintf(stderr, "xmlParserInput: cur > base + use problem\n");
74 }
75 fprintf(stderr,"buffer %x : content %x, cur %d, use %d, size %d\n",
76 (int) in, (int) in->buf->buffer->content, in->cur - in->base,
77 in->buf->buffer->use, in->buf->buffer->size);
78}
79
Daniel Veillardb05deb71999-08-10 19:04:08 +000080#else
81#define CHECK_BUFFER(in)
82#endif
83
Daniel Veillarde2d034d1999-07-27 19:52:06 +000084
85/**
86 * xmlParserInputRead:
87 * @in: an XML parser input
88 * @len: an indicative size for the lookahead
89 *
90 * This function refresh the input for the parser. It doesn't try to
91 * preserve pointers to the input buffer, and discard already read data
92 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000093 * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
Daniel Veillarde2d034d1999-07-27 19:52:06 +000094 * end of this entity
95 */
96int
97xmlParserInputRead(xmlParserInputPtr in, int len) {
98 int ret;
99 int used;
100 int index;
101
102#ifdef DEBUG_INPUT
103 fprintf(stderr, "Read\n");
104#endif
105 if (in->buf == NULL) return(-1);
106 if (in->base == NULL) return(-1);
107 if (in->cur == NULL) return(-1);
108 if (in->buf->buffer == NULL) return(-1);
109
110 CHECK_BUFFER(in);
111
112 used = in->cur - in->buf->buffer->content;
113 ret = xmlBufferShrink(in->buf->buffer, used);
114 if (ret > 0) {
115 in->cur -= ret;
116 in->consumed += ret;
117 }
118 ret = xmlParserInputBufferRead(in->buf, len);
119 if (in->base != in->buf->buffer->content) {
120 /*
121 * the buffer has been realloced
122 */
123 index = in->cur - in->base;
124 in->base = in->buf->buffer->content;
125 in->cur = &in->buf->buffer->content[index];
126 }
127
128 CHECK_BUFFER(in);
129
130 return(ret);
131}
132
133/**
134 * xmlParserInputGrow:
135 * @in: an XML parser input
136 * @len: an indicative size for the lookahead
137 *
138 * This function increase the input for the parser. It tries to
139 * preserve pointers to the input buffer, and keep already read data
140 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000141 * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000142 * end of this entity
143 */
144int
145xmlParserInputGrow(xmlParserInputPtr in, int len) {
146 int ret;
147 int index;
148
149#ifdef DEBUG_INPUT
150 fprintf(stderr, "Grow\n");
151#endif
152 if (in->buf == NULL) return(-1);
153 if (in->base == NULL) return(-1);
154 if (in->cur == NULL) return(-1);
155 if (in->buf->buffer == NULL) return(-1);
156
157 CHECK_BUFFER(in);
158
159 index = in->cur - in->base;
160 if (in->buf->buffer->use > index + INPUT_CHUNK) {
161
162 CHECK_BUFFER(in);
163
164 return(0);
165 }
166 ret = xmlParserInputBufferGrow(in->buf, len);
167 if (in->base != in->buf->buffer->content) {
168 /*
169 * the buffer has been realloced
170 */
171 index = in->cur - in->base;
172 in->base = in->buf->buffer->content;
173 in->cur = &in->buf->buffer->content[index];
174 }
175
176 CHECK_BUFFER(in);
177
178 return(ret);
179}
180
181/**
182 * xmlParserInputShrink:
183 * @in: an XML parser input
184 *
185 * This function removes used input for the parser.
186 */
187void
188xmlParserInputShrink(xmlParserInputPtr in) {
189 int used;
190 int ret;
191 int index;
192
193#ifdef DEBUG_INPUT
194 fprintf(stderr, "Shrink\n");
195#endif
196 if (in->buf == NULL) return;
197 if (in->base == NULL) return;
198 if (in->cur == NULL) return;
199 if (in->buf->buffer == NULL) return;
200
201 CHECK_BUFFER(in);
202
203 used = in->cur - in->buf->buffer->content;
204 if (used > INPUT_CHUNK) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000205 ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000206 if (ret > 0) {
207 in->cur -= ret;
208 in->consumed += ret;
209 }
210 }
211
212 CHECK_BUFFER(in);
213
214 if (in->buf->buffer->use > INPUT_CHUNK) {
215 return;
216 }
217 xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
218 if (in->base != in->buf->buffer->content) {
219 /*
220 * the buffer has been realloced
221 */
222 index = in->cur - in->base;
223 in->base = in->buf->buffer->content;
224 in->cur = &in->buf->buffer->content[index];
225 }
226
227 CHECK_BUFFER(in);
228}
229
Daniel Veillard260a68f1998-08-13 03:39:55 +0000230/************************************************************************
231 * *
232 * Parser stacks related functions and macros *
233 * *
234 ************************************************************************/
Daniel Veillard011b63c1999-06-02 17:44:04 +0000235
236int xmlSubstituteEntitiesDefaultValue = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000237int xmlDoValidityCheckingDefaultValue = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000238
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239/*
240 * Generic function for accessing stacks in the Parser Context
241 */
242
243#define PUSH_AND_POP(type, name) \
Daniel Veillard517752b1999-04-05 12:20:10 +0000244extern int name##Push(xmlParserCtxtPtr ctxt, type value) { \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000245 if (ctxt->name##Nr >= ctxt->name##Max) { \
246 ctxt->name##Max *= 2; \
Daniel Veillard6454aec1999-09-02 22:04:43 +0000247 ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
249 if (ctxt->name##Tab == NULL) { \
250 fprintf(stderr, "realloc failed !\n"); \
251 exit(1); \
252 } \
253 } \
254 ctxt->name##Tab[ctxt->name##Nr] = value; \
255 ctxt->name = value; \
256 return(ctxt->name##Nr++); \
257} \
Daniel Veillard517752b1999-04-05 12:20:10 +0000258extern type name##Pop(xmlParserCtxtPtr ctxt) { \
Daniel Veillardd692aa41999-02-28 21:54:31 +0000259 type ret; \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 if (ctxt->name##Nr <= 0) return(0); \
261 ctxt->name##Nr--; \
Daniel Veillardccb09631998-10-27 06:21:04 +0000262 if (ctxt->name##Nr > 0) \
263 ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \
264 else \
265 ctxt->name = NULL; \
Daniel Veillardd692aa41999-02-28 21:54:31 +0000266 ret = ctxt->name##Tab[ctxt->name##Nr]; \
267 ctxt->name##Tab[ctxt->name##Nr] = 0; \
268 return(ret); \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000269} \
270
271PUSH_AND_POP(xmlParserInputPtr, input)
272PUSH_AND_POP(xmlNodePtr, node)
273
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000274/*
275 * Macros for accessing the content. Those should be used only by the parser,
276 * and not exported.
277 *
278 * Dirty macros, i.e. one need to make assumption on the context to use them
279 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000280 * CUR_PTR return the current pointer to the xmlChar to be parsed.
281 * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000282 * in ISO-Latin or UTF-8, and the current 16 bit value if compiled
283 * in UNICODE mode. This should be used internally by the parser
284 * only to compare to ASCII values otherwise it would break when
285 * running with UTF-8 encoding.
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000286 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000287 * to compare on ASCII based substring.
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000288 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000289 * strings within the parser.
290 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000291 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000292 *
293 * CURRENT Returns the current char value, with the full decoding of
294 * UTF-8 if we are using this mode. It returns an int.
295 * NEXT Skip to the next character, this does the proper decoding
296 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
Daniel Veillard011b63c1999-06-02 17:44:04 +0000297 * COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000298 */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299
Daniel Veillardb05deb71999-08-10 19:04:08 +0000300#define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000301#define SKIP(val) ctxt->input->cur += (val)
302#define NXT(val) ctxt->input->cur[(val)]
303#define CUR_PTR ctxt->input->cur
Daniel Veillardb05deb71999-08-10 19:04:08 +0000304#define SHRINK xmlParserInputShrink(ctxt->input); \
305 if ((*ctxt->input->cur == 0) && \
306 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
307 xmlPopInput(ctxt)
308
309#define GROW xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
310 if ((*ctxt->input->cur == 0) && \
311 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
312 xmlPopInput(ctxt)
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000313
314#define SKIP_BLANKS \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000315 do { \
316 while (IS_BLANK(CUR)) NEXT; \
317 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
318 if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); \
319 } while (IS_BLANK(CUR));
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000320
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000321#define CURRENT (*ctxt->input->cur)
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000322#define NEXT { \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000323 if (ctxt->token != 0) ctxt->token = 0; \
324 else { \
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000325 if ((*ctxt->input->cur == 0) && \
326 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) { \
327 xmlPopInput(ctxt); \
328 } else { \
329 if (*(ctxt->input->cur) == '\n') { \
330 ctxt->input->line++; ctxt->input->col = 1; \
331 } else ctxt->input->col++; \
332 ctxt->input->cur++; \
333 if (*ctxt->input->cur == 0) \
334 xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000335 } \
336 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
337 if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); \
338}}
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000339
Daniel Veillard260a68f1998-08-13 03:39:55 +0000340
Daniel Veillardb05deb71999-08-10 19:04:08 +0000341/************************************************************************
342 * *
343 * Commodity functions to handle entities processing *
344 * *
345 ************************************************************************/
Daniel Veillard260a68f1998-08-13 03:39:55 +0000346
Daniel Veillard11e00581998-10-24 18:27:49 +0000347/**
348 * xmlPopInput:
349 * @ctxt: an XML parser context
350 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000351 * xmlPopInput: the current input pointed by ctxt->input came to an end
352 * pop it and return the next char.
353 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000354 * Returns the current xmlChar in the parser context
Daniel Veillard260a68f1998-08-13 03:39:55 +0000355 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000356xmlChar
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000357xmlPopInput(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000358 if (ctxt->inputNr == 1) return(0); /* End of main Input */
Daniel Veillardbc50b591999-03-01 12:28:53 +0000359 xmlFreeInputStream(inputPop(ctxt));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000360 if ((*ctxt->input->cur == 0) &&
361 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
362 return(xmlPopInput(ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000363 return(CUR);
364}
365
Daniel Veillard11e00581998-10-24 18:27:49 +0000366/**
367 * xmlPushInput:
368 * @ctxt: an XML parser context
369 * @input: an XML parser input fragment (entity, XML fragment ...).
370 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000371 * xmlPushInput: switch to a new input stream which is stacked on top
372 * of the previous one(s).
373 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000374void
375xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000376 if (input == NULL) return;
377 inputPush(ctxt, input);
378}
379
Daniel Veillard11e00581998-10-24 18:27:49 +0000380/**
Daniel Veillardd692aa41999-02-28 21:54:31 +0000381 * xmlFreeInputStream:
Daniel Veillardb05deb71999-08-10 19:04:08 +0000382 * @input: an xmlP arserInputPtr
Daniel Veillardd692aa41999-02-28 21:54:31 +0000383 *
384 * Free up an input stream.
385 */
386void
387xmlFreeInputStream(xmlParserInputPtr input) {
388 if (input == NULL) return;
389
Daniel Veillard6454aec1999-09-02 22:04:43 +0000390 if (input->filename != NULL) xmlFree((char *) input->filename);
391 if (input->directory != NULL) xmlFree((char *) input->directory);
Daniel Veillardd692aa41999-02-28 21:54:31 +0000392 if ((input->free != NULL) && (input->base != NULL))
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000393 input->free((xmlChar *) input->base);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000394 if (input->buf != NULL)
395 xmlFreeParserInputBuffer(input->buf);
Daniel Veillardd692aa41999-02-28 21:54:31 +0000396 memset(input, -1, sizeof(xmlParserInput));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000397 xmlFree(input);
Daniel Veillardd692aa41999-02-28 21:54:31 +0000398}
399
400/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000401 * xmlNewInputStream:
402 * @ctxt: an XML parser context
403 *
404 * Create a new input stream structure
405 * Returns the new input stream or NULL
406 */
407xmlParserInputPtr
408xmlNewInputStream(xmlParserCtxtPtr ctxt) {
409 xmlParserInputPtr input;
410
Daniel Veillard6454aec1999-09-02 22:04:43 +0000411 input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000412 if (input == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000413 ctxt->errNo = XML_ERR_NO_MEMORY;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000414 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000415 ctxt->sax->error(ctxt->userData,
416 "malloc: couldn't allocate a new input stream\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000417 ctxt->errNo = XML_ERR_NO_MEMORY;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000418 return(NULL);
419 }
420 input->filename = NULL;
421 input->directory = NULL;
422 input->base = NULL;
423 input->cur = NULL;
424 input->buf = NULL;
425 input->line = 1;
426 input->col = 1;
427 input->buf = NULL;
428 input->free = NULL;
429 input->consumed = 0;
430 return(input);
431}
432
433/**
Daniel Veillard11e00581998-10-24 18:27:49 +0000434 * xmlNewEntityInputStream:
435 * @ctxt: an XML parser context
436 * @entity: an Entity pointer
437 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000438 * Create a new input stream based on an xmlEntityPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +0000439 *
440 * Returns the new input stream or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000441 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000442xmlParserInputPtr
443xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000444 xmlParserInputPtr input;
445
446 if (entity == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000447 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde3bffb91998-11-08 14:40:56 +0000448 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +0000449 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000450 "internal: xmlNewEntityInputStream entity = NULL\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000451 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillardccb09631998-10-27 06:21:04 +0000452 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000453 }
454 if (entity->content == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000455 switch (entity->type) {
456 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000457 ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000458 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
459 ctxt->sax->error(ctxt->userData,
460 "xmlNewEntityInputStream unparsed entity !\n");
461 break;
462 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
463 case XML_EXTERNAL_PARAMETER_ENTITY:
464 return(xmlLoadExternalEntity((char *) entity->SystemID,
465 (char *) entity->ExternalID, ctxt->input));
466 case XML_INTERNAL_GENERAL_ENTITY:
467 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
468 ctxt->sax->error(ctxt->userData,
469 "Internal entity %s without content !\n", entity->name);
470 break;
471 case XML_INTERNAL_PARAMETER_ENTITY:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000472 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000473 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
474 ctxt->sax->error(ctxt->userData,
475 "Internal parameter entity %s without content !\n", entity->name);
476 break;
477 case XML_INTERNAL_PREDEFINED_ENTITY:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000478 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000479 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
480 ctxt->sax->error(ctxt->userData,
481 "Predefined entity %s without content !\n", entity->name);
482 break;
483 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000484 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000485 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000486 input = xmlNewInputStream(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000487 if (input == NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000488 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000489 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000490 input->filename = (char *) entity->SystemID; /* TODO !!! char <- xmlChar */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000491 input->base = entity->content;
492 input->cur = entity->content;
Daniel Veillardccb09631998-10-27 06:21:04 +0000493 return(input);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000494}
495
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000496/**
497 * xmlNewStringInputStream:
498 * @ctxt: an XML parser context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000499 * @buffer: an memory buffer
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000500 *
501 * Create a new input stream based on a memory buffer.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000502 * Returns the new input stream
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000503 */
504xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000505xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000506 xmlParserInputPtr input;
507
Daniel Veillardb05deb71999-08-10 19:04:08 +0000508 if (buffer == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000509 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000510 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +0000511 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000512 "internal: xmlNewStringInputStream string = NULL\n");
513 return(NULL);
514 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000515 input = xmlNewInputStream(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000516 if (input == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000517 return(NULL);
518 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000519 input->base = buffer;
520 input->cur = buffer;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000521 return(input);
522}
523
Daniel Veillard011b63c1999-06-02 17:44:04 +0000524/**
525 * xmlNewInputFromFile:
526 * @ctxt: an XML parser context
527 * @filename: the filename to use as entity
528 *
529 * Create a new input stream based on a file.
530 *
531 * Returns the new input stream or NULL in case of error
532 */
533xmlParserInputPtr
534xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000535 xmlParserInputBufferPtr buf;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000536 xmlParserInputPtr inputStream;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000537 char *directory = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000538
Daniel Veillardb05deb71999-08-10 19:04:08 +0000539 if (ctxt == NULL) return(NULL);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000540 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000541 if (buf == NULL) {
542 char name[1024];
Daniel Veillard011b63c1999-06-02 17:44:04 +0000543
Daniel Veillardb05deb71999-08-10 19:04:08 +0000544 if ((ctxt->input != NULL) && (ctxt->input->directory != NULL)) {
545#ifdef WIN32
546 sprintf(name, "%s\\%s", ctxt->input->directory, filename);
547#else
548 sprintf(name, "%s/%s", ctxt->input->directory, filename);
549#endif
550 buf = xmlParserInputBufferCreateFilename(name,
551 XML_CHAR_ENCODING_NONE);
552 if (buf != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000553 directory = xmlMemStrdup(ctxt->input->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000554 }
555 if ((buf == NULL) && (ctxt->directory != NULL)) {
556#ifdef WIN32
557 sprintf(name, "%s\\%s", ctxt->directory, filename);
558#else
559 sprintf(name, "%s/%s", ctxt->directory, filename);
560#endif
561 buf = xmlParserInputBufferCreateFilename(name,
562 XML_CHAR_ENCODING_NONE);
563 if (buf != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000564 directory = xmlMemStrdup(ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000565 }
566 if (buf == NULL)
567 return(NULL);
568 }
569 if (directory == NULL)
570 directory = xmlParserGetDirectory(filename);
571
572 inputStream = xmlNewInputStream(ctxt);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000573 if (inputStream == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000574 if (directory != NULL) xmlFree((char *) directory);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000575 return(NULL);
576 }
577
Daniel Veillard6454aec1999-09-02 22:04:43 +0000578 inputStream->filename = xmlMemStrdup(filename);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000579 inputStream->directory = directory;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000580 inputStream->buf = buf;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000581
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000582 inputStream->base = inputStream->buf->buffer->content;
583 inputStream->cur = inputStream->buf->buffer->content;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000584 if ((ctxt->directory == NULL) && (directory != NULL))
585 ctxt->directory = directory;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000586 return(inputStream);
587}
588
589/************************************************************************
590 * *
Daniel Veillardb05deb71999-08-10 19:04:08 +0000591 * Commodity functions to handle parser contexts *
592 * *
593 ************************************************************************/
594
595/**
596 * xmlInitParserCtxt:
597 * @ctxt: an XML parser context
598 *
599 * Initialize a parser context
600 */
601
602void
603xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
604{
605 xmlSAXHandler *sax;
606
Daniel Veillard6454aec1999-09-02 22:04:43 +0000607 sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000608 if (sax == NULL) {
609 fprintf(stderr, "xmlInitParserCtxt: out of memory\n");
610 }
611
612 /* Allocate the Input stack */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000613 ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000614 ctxt->inputNr = 0;
615 ctxt->inputMax = 5;
616 ctxt->input = NULL;
617 ctxt->version = NULL;
618 ctxt->encoding = NULL;
619 ctxt->standalone = -1;
620 ctxt->hasExternalSubset = 0;
621 ctxt->hasPErefs = 0;
622 ctxt->html = 0;
623 ctxt->external = 0;
624 ctxt->instate = XML_PARSER_PROLOG;
625 ctxt->token = 0;
626 ctxt->directory = NULL;
627
628 /* Allocate the Node stack */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000629 ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000630 ctxt->nodeNr = 0;
631 ctxt->nodeMax = 10;
632 ctxt->node = NULL;
633
634 if (sax == NULL) ctxt->sax = &xmlDefaultSAXHandler;
635 else {
636 ctxt->sax = sax;
637 memcpy(sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
638 }
639 ctxt->userData = ctxt;
640 ctxt->myDoc = NULL;
641 ctxt->wellFormed = 1;
642 ctxt->valid = 1;
643 ctxt->validate = xmlDoValidityCheckingDefaultValue;
644 ctxt->vctxt.userData = ctxt;
645 ctxt->vctxt.error = xmlParserValidityError;
646 ctxt->vctxt.warning = xmlParserValidityWarning;
647 ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
648 ctxt->record_info = 0;
649 xmlInitNodeInfoSeq(&ctxt->node_seq);
650}
651
652/**
653 * xmlFreeParserCtxt:
654 * @ctxt: an XML parser context
655 *
656 * Free all the memory used by a parser context. However the parsed
657 * document in ctxt->myDoc is not freed.
658 */
659
660void
661xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
662{
663 xmlParserInputPtr input;
664
665 if (ctxt == NULL) return;
666
667 while ((input = inputPop(ctxt)) != NULL) {
668 xmlFreeInputStream(input);
669 }
670
Daniel Veillard6454aec1999-09-02 22:04:43 +0000671 if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
672 if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
673 if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
674 if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000675 if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
Daniel Veillard6454aec1999-09-02 22:04:43 +0000676 xmlFree(ctxt->sax);
677 if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
678 xmlFree(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000679}
680
681/**
682 * xmlNewParserCtxt:
683 *
684 * Allocate and initialize a new parser context.
685 *
686 * Returns the xmlParserCtxtPtr or NULL
687 */
688
689xmlParserCtxtPtr
690xmlNewParserCtxt()
691{
692 xmlParserCtxtPtr ctxt;
693
Daniel Veillard6454aec1999-09-02 22:04:43 +0000694 ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000695 if (ctxt == NULL) {
696 fprintf(stderr, "xmlNewParserCtxt : cannot allocate context\n");
697 perror("malloc");
698 return(NULL);
699 }
700 xmlInitParserCtxt(ctxt);
701 return(ctxt);
702}
703
704/**
705 * xmlClearParserCtxt:
706 * @ctxt: an XML parser context
707 *
708 * Clear (release owned resources) and reinitialize a parser context
709 */
710
711void
712xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
713{
714 xmlClearNodeInfoSeq(&ctxt->node_seq);
715 xmlInitParserCtxt(ctxt);
716}
717
718/************************************************************************
719 * *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000720 * Commodity functions to handle entities *
721 * *
722 ************************************************************************/
723
Daniel Veillardb05deb71999-08-10 19:04:08 +0000724void xmlParserHandleReference(xmlParserCtxtPtr ctxt);
725void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
726
727/**
728 * xmlParseCharRef:
729 * @ctxt: an XML parser context
730 *
731 * parse Reference declarations
732 *
733 * [66] CharRef ::= '&#' [0-9]+ ';' |
734 * '&#x' [0-9a-fA-F]+ ';'
735 *
736 * [ WFC: Legal Character ]
737 * Characters referred to using character references must match the
738 * production for Char.
739 *
740 * Returns the value parsed (as an int)
741 */
742int
743xmlParseCharRef(xmlParserCtxtPtr ctxt) {
744 int val = 0;
745
746 if (ctxt->token != 0) {
Daniel Veillard35008381999-10-25 13:15:52 +0000747fprintf(stderr, "xmlParseCharRef : ctxt->token != 0\n");
Daniel Veillardb05deb71999-08-10 19:04:08 +0000748 val = ctxt->token;
749 ctxt->token = 0;
750 return(val);
751 }
752 if ((CUR == '&') && (NXT(1) == '#') &&
753 (NXT(2) == 'x')) {
754 SKIP(3);
755 while (CUR != ';') {
756 if ((CUR >= '0') && (CUR <= '9'))
757 val = val * 16 + (CUR - '0');
758 else if ((CUR >= 'a') && (CUR <= 'f'))
759 val = val * 16 + (CUR - 'a') + 10;
760 else if ((CUR >= 'A') && (CUR <= 'F'))
761 val = val * 16 + (CUR - 'A') + 10;
762 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000763 ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000764 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
765 ctxt->sax->error(ctxt->userData,
766 "xmlParseCharRef: invalid hexadecimal value\n");
767 ctxt->wellFormed = 0;
768 val = 0;
769 break;
770 }
771 NEXT;
772 }
773 if (CUR == ';')
Daniel Veillard35008381999-10-25 13:15:52 +0000774 SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
Daniel Veillardb05deb71999-08-10 19:04:08 +0000775 } else if ((CUR == '&') && (NXT(1) == '#')) {
776 SKIP(2);
777 while (CUR != ';') {
778 if ((CUR >= '0') && (CUR <= '9'))
779 val = val * 10 + (CUR - '0');
780 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000781 ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000782 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
783 ctxt->sax->error(ctxt->userData,
784 "xmlParseCharRef: invalid decimal value\n");
785 ctxt->wellFormed = 0;
786 val = 0;
787 break;
788 }
789 NEXT;
790 }
791 if (CUR == ';')
Daniel Veillard35008381999-10-25 13:15:52 +0000792 SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
Daniel Veillardb05deb71999-08-10 19:04:08 +0000793 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000794 ctxt->errNo = XML_ERR_INVALID_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000795 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
796 ctxt->sax->error(ctxt->userData,
797 "xmlParseCharRef: invalid value\n");
798 ctxt->wellFormed = 0;
799 }
800
801 /*
802 * [ WFC: Legal Character ]
803 * Characters referred to using character references must match the
804 * production for Char.
805 */
806 if (IS_CHAR(val)) {
807 return(val);
808 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000809 ctxt->errNo = XML_ERR_INVALID_CHAR;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000810 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000811 ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
Daniel Veillardb05deb71999-08-10 19:04:08 +0000812 val);
813 ctxt->wellFormed = 0;
814 }
815 return(0);
816}
817
818/**
819 * xmlParserHandleReference:
820 * @ctxt: the parser context
821 *
822 * [67] Reference ::= EntityRef | CharRef
823 *
824 * [68] EntityRef ::= '&' Name ';'
825 *
826 * [ WFC: Entity Declared ]
827 * the Name given in the entity reference must match that in an entity
828 * declaration, except that well-formed documents need not declare any
829 * of the following entities: amp, lt, gt, apos, quot.
830 *
831 * [ WFC: Parsed Entity ]
832 * An entity reference must not contain the name of an unparsed entity
833 *
834 * [66] CharRef ::= '&#' [0-9]+ ';' |
835 * '&#x' [0-9a-fA-F]+ ';'
836 *
837 * A PEReference may have been detectect in the current input stream
838 * the handling is done accordingly to
839 * http://www.w3.org/TR/REC-xml#entproc
840 */
841void
842xmlParserHandleReference(xmlParserCtxtPtr ctxt) {
843 xmlParserInputPtr input;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000844 xmlChar *name;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000845 xmlEntityPtr ent = NULL;
846
Daniel Veillard35008381999-10-25 13:15:52 +0000847 if (ctxt->token != 0) {
848fprintf(stderr, "xmlParserHandleReference : ctxt->token != 0\n");
849 return;
850 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000851 if (CUR != '&') return;
852 GROW;
853 if ((CUR == '&') && (NXT(1) == '#')) {
854 switch(ctxt->instate) {
855 case XML_PARSER_CDATA_SECTION:
856 return;
857 case XML_PARSER_COMMENT:
858 return;
859 case XML_PARSER_EOF:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000860 ctxt->errNo = XML_ERR_CHARREF_AT_EOF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000861 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
862 ctxt->sax->error(ctxt->userData, "CharRef at EOF\n");
863 ctxt->wellFormed = 0;
864 return;
865 case XML_PARSER_PROLOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000866 ctxt->errNo = XML_ERR_CHARREF_IN_PROLOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000867 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
868 ctxt->sax->error(ctxt->userData, "CharRef in prolog!\n");
869 ctxt->wellFormed = 0;
870 return;
871 case XML_PARSER_EPILOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000872 ctxt->errNo = XML_ERR_CHARREF_IN_EPILOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000873 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
874 ctxt->sax->error(ctxt->userData, "CharRef in epilog!\n");
875 ctxt->wellFormed = 0;
876 return;
877 case XML_PARSER_DTD:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000878 ctxt->errNo = XML_ERR_CHARREF_IN_DTD;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000879 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
880 ctxt->sax->error(ctxt->userData,
881 "CharRef are forbiden in DTDs!\n");
882 ctxt->wellFormed = 0;
883 return;
884 case XML_PARSER_ENTITY_DECL:
885 /* we just ignore it there */
886 return;
887 case XML_PARSER_ENTITY_VALUE:
888 /*
889 * NOTE: in the case of entity values, we don't do the
890 * substitution here since we need the litteral
891 * entity value to be able to save the internal
892 * subset of the document.
893 * This will be handled by xmlDecodeEntities
894 */
895 return;
896 case XML_PARSER_CONTENT:
897 case XML_PARSER_ATTRIBUTE_VALUE:
Daniel Veillardb96e6431999-08-29 21:02:19 +0000898 /* !!! this may not be Ok for UTF-8, multibyte sequence */
Daniel Veillardb05deb71999-08-10 19:04:08 +0000899 ctxt->token = xmlParseCharRef(ctxt);
900 return;
901 }
902 return;
903 }
904
905 switch(ctxt->instate) {
906 case XML_PARSER_CDATA_SECTION:
907 return;
908 case XML_PARSER_COMMENT:
909 return;
910 case XML_PARSER_EOF:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000911 ctxt->errNo = XML_ERR_ENTITYREF_AT_EOF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000912 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
913 ctxt->sax->error(ctxt->userData, "Reference at EOF\n");
914 ctxt->wellFormed = 0;
915 return;
916 case XML_PARSER_PROLOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000917 ctxt->errNo = XML_ERR_ENTITYREF_IN_PROLOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000918 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
919 ctxt->sax->error(ctxt->userData, "Reference in prolog!\n");
920 ctxt->wellFormed = 0;
921 return;
922 case XML_PARSER_EPILOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000923 ctxt->errNo = XML_ERR_ENTITYREF_IN_EPILOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000924 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
925 ctxt->sax->error(ctxt->userData, "Reference in epilog!\n");
926 ctxt->wellFormed = 0;
927 return;
928 case XML_PARSER_ENTITY_VALUE:
929 /*
930 * NOTE: in the case of entity values, we don't do the
931 * substitution here since we need the litteral
932 * entity value to be able to save the internal
933 * subset of the document.
934 * This will be handled by xmlDecodeEntities
935 */
936 return;
937 case XML_PARSER_ATTRIBUTE_VALUE:
938 /*
939 * NOTE: in the case of attributes values, we don't do the
940 * substitution here unless we are in a mode where
941 * the parser is explicitely asked to substitute
942 * entities. The SAX callback is called with values
943 * without entity substitution.
944 * This will then be handled by xmlDecodeEntities
945 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000946 return;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000947 case XML_PARSER_ENTITY_DECL:
948 /*
949 * we just ignore it there
950 * the substitution will be done once the entity is referenced
951 */
952 return;
953 case XML_PARSER_DTD:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000954 ctxt->errNo = XML_ERR_ENTITYREF_IN_DTD;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000955 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
956 ctxt->sax->error(ctxt->userData,
957 "Entity references are forbiden in DTDs!\n");
958 ctxt->wellFormed = 0;
959 return;
960 case XML_PARSER_CONTENT:
Daniel Veillardb96e6431999-08-29 21:02:19 +0000961 return;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000962 }
963
964 NEXT;
965 name = xmlScanName(ctxt);
966 if (name == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000967 ctxt->errNo = XML_ERR_ENTITYREF_NO_NAME;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000968 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
969 ctxt->sax->error(ctxt->userData, "Entity reference: no name\n");
970 ctxt->wellFormed = 0;
971 ctxt->token = '&';
972 return;
973 }
974 if (NXT(xmlStrlen(name)) != ';') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000975 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000976 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
977 ctxt->sax->error(ctxt->userData,
978 "Entity reference: ';' expected\n");
979 ctxt->wellFormed = 0;
980 ctxt->token = '&';
Daniel Veillard6454aec1999-09-02 22:04:43 +0000981 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000982 return;
983 }
984 SKIP(xmlStrlen(name) + 1);
985 if (ctxt->sax != NULL) {
986 if (ctxt->sax->getEntity != NULL)
987 ent = ctxt->sax->getEntity(ctxt->userData, name);
988 }
989
990 /*
991 * [ WFC: Entity Declared ]
992 * the Name given in the entity reference must match that in an entity
993 * declaration, except that well-formed documents need not declare any
994 * of the following entities: amp, lt, gt, apos, quot.
995 */
996 if (ent == NULL)
997 ent = xmlGetPredefinedEntity(name);
998 if (ent == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000999 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001000 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1001 ctxt->sax->error(ctxt->userData,
1002 "Entity reference: entity %s not declared\n",
1003 name);
1004 ctxt->wellFormed = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +00001005 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001006 return;
1007 }
1008
1009 /*
1010 * [ WFC: Parsed Entity ]
1011 * An entity reference must not contain the name of an unparsed entity
1012 */
1013 if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001014 ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001015 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1016 ctxt->sax->error(ctxt->userData,
1017 "Entity reference to unparsed entity %s\n", name);
1018 ctxt->wellFormed = 0;
1019 }
1020
1021 if (ent->type == XML_INTERNAL_PREDEFINED_ENTITY) {
1022 ctxt->token = ent->content[0];
Daniel Veillard6454aec1999-09-02 22:04:43 +00001023 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001024 return;
1025 }
1026 input = xmlNewEntityInputStream(ctxt, ent);
1027 xmlPushInput(ctxt, input);
Daniel Veillard6454aec1999-09-02 22:04:43 +00001028 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001029 return;
1030}
1031
1032/**
1033 * xmlParserHandlePEReference:
1034 * @ctxt: the parser context
1035 *
1036 * [69] PEReference ::= '%' Name ';'
1037 *
1038 * [ WFC: No Recursion ]
1039 * TODO A parsed entity must not contain a recursive
1040 * reference to itself, either directly or indirectly.
1041 *
1042 * [ WFC: Entity Declared ]
1043 * In a document without any DTD, a document with only an internal DTD
1044 * subset which contains no parameter entity references, or a document
1045 * with "standalone='yes'", ... ... The declaration of a parameter
1046 * entity must precede any reference to it...
1047 *
1048 * [ VC: Entity Declared ]
1049 * In a document with an external subset or external parameter entities
1050 * with "standalone='no'", ... ... The declaration of a parameter entity
1051 * must precede any reference to it...
1052 *
1053 * [ WFC: In DTD ]
1054 * Parameter-entity references may only appear in the DTD.
1055 * NOTE: misleading but this is handled.
1056 *
1057 * A PEReference may have been detected in the current input stream
1058 * the handling is done accordingly to
1059 * http://www.w3.org/TR/REC-xml#entproc
1060 * i.e.
1061 * - Included in literal in entity values
1062 * - Included as Paraemeter Entity reference within DTDs
1063 */
1064void
1065xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001066 xmlChar *name;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001067 xmlEntityPtr entity = NULL;
1068 xmlParserInputPtr input;
1069
Daniel Veillard35008381999-10-25 13:15:52 +00001070 if (ctxt->token != 0) {
1071fprintf(stderr, "xmlParserHandlePEReference : ctxt->token != 0\n");
1072 return;
1073 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001074 if (CUR != '%') return;
1075 switch(ctxt->instate) {
1076 case XML_PARSER_CDATA_SECTION:
1077 return;
1078 case XML_PARSER_COMMENT:
1079 return;
1080 case XML_PARSER_EOF:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001081 ctxt->errNo = XML_ERR_PEREF_AT_EOF;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001082 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1083 ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
1084 ctxt->wellFormed = 0;
1085 return;
1086 case XML_PARSER_PROLOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001087 ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001088 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1089 ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
1090 ctxt->wellFormed = 0;
1091 return;
1092 case XML_PARSER_ENTITY_DECL:
1093 case XML_PARSER_CONTENT:
1094 case XML_PARSER_ATTRIBUTE_VALUE:
1095 /* we just ignore it there */
1096 return;
1097 case XML_PARSER_EPILOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001098 ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001099 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1100 ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
1101 ctxt->wellFormed = 0;
1102 return;
1103 case XML_PARSER_ENTITY_VALUE:
1104 /*
1105 * NOTE: in the case of entity values, we don't do the
1106 * substitution here since we need the litteral
1107 * entity value to be able to save the internal
1108 * subset of the document.
1109 * This will be handled by xmlDecodeEntities
1110 */
1111 return;
1112 case XML_PARSER_DTD:
1113 /*
1114 * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
1115 * In the internal DTD subset, parameter-entity references
1116 * can occur only where markup declarations can occur, not
1117 * within markup declarations.
1118 * In that case this is handled in xmlParseMarkupDecl
1119 */
1120 if ((ctxt->external == 0) && (ctxt->inputNr == 1))
1121 return;
1122 }
1123
1124 NEXT;
1125 name = xmlParseName(ctxt);
1126 if (name == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001127 ctxt->errNo = XML_ERR_PEREF_NO_NAME;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001128 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1129 ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
1130 ctxt->wellFormed = 0;
1131 } else {
1132 if (CUR == ';') {
1133 NEXT;
1134 if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
1135 entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
1136 if (entity == NULL) {
1137
1138 /*
1139 * [ WFC: Entity Declared ]
1140 * In a document without any DTD, a document with only an
1141 * internal DTD subset which contains no parameter entity
1142 * references, or a document with "standalone='yes'", ...
1143 * ... The declaration of a parameter entity must precede
1144 * any reference to it...
1145 */
1146 if ((ctxt->standalone == 1) ||
1147 ((ctxt->hasExternalSubset == 0) &&
1148 (ctxt->hasPErefs == 0))) {
1149 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1150 ctxt->sax->error(ctxt->userData,
1151 "PEReference: %%%s; not found\n", name);
1152 ctxt->wellFormed = 0;
1153 } else {
1154 /*
1155 * [ VC: Entity Declared ]
1156 * In a document with an external subset or external
1157 * parameter entities with "standalone='no'", ...
1158 * ... The declaration of a parameter entity must precede
1159 * any reference to it...
1160 */
1161 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1162 ctxt->sax->warning(ctxt->userData,
1163 "PEReference: %%%s; not found\n", name);
1164 ctxt->valid = 0;
1165 }
1166 } else {
1167 if ((entity->type == XML_INTERNAL_PARAMETER_ENTITY) ||
1168 (entity->type == XML_EXTERNAL_PARAMETER_ENTITY)) {
1169 /*
1170 * TODO !!!! handle the extra spaces added before and after
1171 * c.f. http://www.w3.org/TR/REC-xml#as-PE
1172 * TODO !!!! Avoid quote processing in parameters value
1173 * c.f. http://www.w3.org/TR/REC-xml#inliteral
1174 */
1175 input = xmlNewEntityInputStream(ctxt, entity);
1176 xmlPushInput(ctxt, input);
1177 } else {
1178 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1179 ctxt->sax->error(ctxt->userData,
1180 "xmlHandlePEReference: %s is not a parameter entity\n",
1181 name);
1182 ctxt->wellFormed = 0;
1183 }
1184 }
1185 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001186 ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001187 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1188 ctxt->sax->error(ctxt->userData,
1189 "xmlHandlePEReference: expecting ';'\n");
1190 ctxt->wellFormed = 0;
1191 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00001192 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001193 }
1194}
1195
Daniel Veillard011b63c1999-06-02 17:44:04 +00001196/*
1197 * Macro used to grow the current buffer.
1198 */
1199#define growBuffer(buffer) { \
1200 buffer##_size *= 2; \
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001201 buffer = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
Daniel Veillard011b63c1999-06-02 17:44:04 +00001202 if (buffer == NULL) { \
1203 perror("realloc failed"); \
1204 exit(1); \
1205 } \
1206}
1207
Daniel Veillard011b63c1999-06-02 17:44:04 +00001208/**
1209 * xmlDecodeEntities:
1210 * @ctxt: the parser context
1211 * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1212 * @len: the len to decode (in bytes !), -1 for no size limit
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001213 * @end: an end marker xmlChar, 0 if none
1214 * @end2: an end marker xmlChar, 0 if none
1215 * @end3: an end marker xmlChar, 0 if none
Daniel Veillard011b63c1999-06-02 17:44:04 +00001216 *
1217 * [67] Reference ::= EntityRef | CharRef
1218 *
1219 * [69] PEReference ::= '%' Name ';'
1220 *
1221 * Returns A newly allocated string with the substitution done. The caller
1222 * must deallocate it !
1223 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001224xmlChar *
Daniel Veillard011b63c1999-06-02 17:44:04 +00001225xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001226 xmlChar end, xmlChar end2, xmlChar end3) {
1227 xmlChar *buffer = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001228 int buffer_size = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001229 xmlChar *out = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001230
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001231 xmlChar *current = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001232 xmlEntityPtr ent;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001233 int nbchars = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001234 unsigned int max = (unsigned int) len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001235 xmlChar cur;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001236
1237 /*
1238 * allocate a translation buffer.
1239 */
1240 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001241 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard011b63c1999-06-02 17:44:04 +00001242 if (buffer == NULL) {
1243 perror("xmlDecodeEntities: malloc failed");
1244 return(NULL);
1245 }
1246 out = buffer;
1247
1248 /*
1249 * Ok loop until we reach one of the ending char or a size limit.
1250 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00001251 cur = CUR;
1252 while ((nbchars < max) && (cur != end) &&
1253 (cur != end2) && (cur != end3)) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00001254
Daniel Veillardb05deb71999-08-10 19:04:08 +00001255 if (cur == 0) break;
1256 if ((cur == '&') && (NXT(1) == '#')) {
1257 int val = xmlParseCharRef(ctxt);
1258 *out++ = val;
1259 nbchars += 3;
1260 } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
1261 ent = xmlParseEntityRef(ctxt);
1262 if ((ent != NULL) &&
1263 (ctxt->replaceEntities != 0)) {
1264 current = ent->content;
1265 while (*current != 0) {
1266 *out++ = *current++;
1267 if (out - buffer > buffer_size - 100) {
1268 int index = out - buffer;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001269
Daniel Veillardb05deb71999-08-10 19:04:08 +00001270 growBuffer(buffer);
1271 out = &buffer[index];
Daniel Veillard011b63c1999-06-02 17:44:04 +00001272 }
1273 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001274 nbchars += 3 + xmlStrlen(ent->name);
1275 } else if (ent != NULL) {
1276 int i = xmlStrlen(ent->name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001277 const xmlChar *cur = ent->name;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001278
1279 nbchars += i + 2;
1280 *out++ = '&';
1281 if (out - buffer > buffer_size - i - 100) {
1282 int index = out - buffer;
1283
1284 growBuffer(buffer);
1285 out = &buffer[index];
1286 }
1287 for (;i > 0;i--)
1288 *out++ = *cur++;
1289 *out++ = ';';
Daniel Veillard011b63c1999-06-02 17:44:04 +00001290 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001291 } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00001292 /*
1293 * a PEReference induce to switch the entity flow,
1294 * we break here to flush the current set of chars
1295 * parsed if any. We will be called back later.
1296 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001297 if (nbchars != 0) break;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001298
1299 xmlParsePEReference(ctxt);
1300
1301 /*
1302 * Pop-up of finished entities.
1303 */
1304 while ((CUR == 0) && (ctxt->inputNr > 1))
1305 xmlPopInput(ctxt);
1306
Daniel Veillardb05deb71999-08-10 19:04:08 +00001307 break;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001308 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001309 /* invalid for UTF-8 , use COPY(out); !!!!!! */
Daniel Veillardb05deb71999-08-10 19:04:08 +00001310 *out++ = cur;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001311 nbchars++;
Raph Levien05240da1999-06-15 21:27:11 +00001312 if (out - buffer > buffer_size - 100) {
1313 int index = out - buffer;
1314
1315 growBuffer(buffer);
1316 out = &buffer[index];
1317 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00001318 NEXT;
1319 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001320 cur = CUR;
Daniel Veillard011b63c1999-06-02 17:44:04 +00001321 }
1322 *out++ = 0;
1323 return(buffer);
1324}
1325
Daniel Veillard260a68f1998-08-13 03:39:55 +00001326
1327/************************************************************************
1328 * *
Daniel Veillard27d88741999-05-29 11:51:49 +00001329 * Commodity functions to handle encodings *
1330 * *
1331 ************************************************************************/
1332
1333/**
1334 * xmlSwitchEncoding:
1335 * @ctxt: the parser context
Daniel Veillard00fdf371999-10-08 09:40:39 +00001336 * @enc: the encoding value (number)
Daniel Veillard27d88741999-05-29 11:51:49 +00001337 *
1338 * change the input functions when discovering the character encoding
1339 * of a given entity.
Daniel Veillard27d88741999-05-29 11:51:49 +00001340 */
1341void
1342xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
1343{
1344 switch (enc) {
1345 case XML_CHAR_ENCODING_ERROR:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001346 ctxt->errNo = XML_ERR_UNKNOWN_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001347 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1348 ctxt->sax->error(ctxt->userData, "encoding unknown\n");
1349 ctxt->wellFormed = 0;
1350 break;
1351 case XML_CHAR_ENCODING_NONE:
1352 /* let's assume it's UTF-8 without the XML decl */
1353 return;
1354 case XML_CHAR_ENCODING_UTF8:
1355 /* default encoding, no conversion should be needed */
1356 return;
1357 case XML_CHAR_ENCODING_UTF16LE:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001358 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001359 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1360 ctxt->sax->error(ctxt->userData,
1361 "char encoding UTF16 little endian not supported\n");
1362 break;
1363 case XML_CHAR_ENCODING_UTF16BE:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001364 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001365 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1366 ctxt->sax->error(ctxt->userData,
1367 "char encoding UTF16 big endian not supported\n");
1368 break;
1369 case XML_CHAR_ENCODING_UCS4LE:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001370 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001371 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1372 ctxt->sax->error(ctxt->userData,
1373 "char encoding USC4 little endian not supported\n");
1374 break;
1375 case XML_CHAR_ENCODING_UCS4BE:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001376 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001377 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1378 ctxt->sax->error(ctxt->userData,
1379 "char encoding USC4 big endian not supported\n");
1380 break;
1381 case XML_CHAR_ENCODING_EBCDIC:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001382 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001383 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1384 ctxt->sax->error(ctxt->userData,
1385 "char encoding EBCDIC not supported\n");
1386 break;
1387 case XML_CHAR_ENCODING_UCS4_2143:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001388 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001389 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1390 ctxt->sax->error(ctxt->userData,
1391 "char encoding UCS4 2143 not supported\n");
1392 break;
1393 case XML_CHAR_ENCODING_UCS4_3412:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001394 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001395 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1396 ctxt->sax->error(ctxt->userData,
1397 "char encoding UCS4 3412 not supported\n");
1398 break;
1399 case XML_CHAR_ENCODING_UCS2:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001400 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001401 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1402 ctxt->sax->error(ctxt->userData,
1403 "char encoding UCS2 not supported\n");
1404 break;
1405 case XML_CHAR_ENCODING_8859_1:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001406 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001407 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1408 ctxt->sax->error(ctxt->userData,
1409 "char encoding ISO_8859_1 ISO Latin 1 not supported\n");
1410 break;
1411 case XML_CHAR_ENCODING_8859_2:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001412 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001413 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1414 ctxt->sax->error(ctxt->userData,
1415 "char encoding ISO_8859_2 ISO Latin 2 not supported\n");
1416 break;
1417 case XML_CHAR_ENCODING_8859_3:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001418 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001419 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1420 ctxt->sax->error(ctxt->userData,
1421 "char encoding ISO_8859_3 not supported\n");
1422 break;
1423 case XML_CHAR_ENCODING_8859_4:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001424 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001425 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1426 ctxt->sax->error(ctxt->userData,
1427 "char encoding ISO_8859_4 not supported\n");
1428 break;
1429 case XML_CHAR_ENCODING_8859_5:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001430 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001431 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1432 ctxt->sax->error(ctxt->userData,
1433 "char encoding ISO_8859_5 not supported\n");
1434 break;
1435 case XML_CHAR_ENCODING_8859_6:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001436 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001437 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1438 ctxt->sax->error(ctxt->userData,
1439 "char encoding ISO_8859_6 not supported\n");
1440 break;
1441 case XML_CHAR_ENCODING_8859_7:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001442 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001443 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1444 ctxt->sax->error(ctxt->userData,
1445 "char encoding ISO_8859_7 not supported\n");
1446 break;
1447 case XML_CHAR_ENCODING_8859_8:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001448 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001449 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1450 ctxt->sax->error(ctxt->userData,
1451 "char encoding ISO_8859_8 not supported\n");
1452 break;
1453 case XML_CHAR_ENCODING_8859_9:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001454 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001455 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1456 ctxt->sax->error(ctxt->userData,
1457 "char encoding ISO_8859_9 not supported\n");
1458 break;
1459 case XML_CHAR_ENCODING_2022_JP:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001460 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001461 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1462 ctxt->sax->error(ctxt->userData,
1463 "char encoding ISO-2022-JPnot supported\n");
1464 break;
1465 case XML_CHAR_ENCODING_SHIFT_JIS:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001466 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001467 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1468 ctxt->sax->error(ctxt->userData,
1469 "char encoding Shift_JISnot supported\n");
1470 break;
1471 case XML_CHAR_ENCODING_EUC_JP:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001472 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard27d88741999-05-29 11:51:49 +00001473 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1474 ctxt->sax->error(ctxt->userData,
1475 "char encoding EUC-JPnot supported\n");
1476 break;
1477 }
1478}
1479
1480/************************************************************************
1481 * *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001482 * Commodity functions to handle xmlChars *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 * *
1484 ************************************************************************/
1485
Daniel Veillard11e00581998-10-24 18:27:49 +00001486/**
1487 * xmlStrndup:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001488 * @cur: the input xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001489 * @len: the len of @cur
1490 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001491 * a strndup for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001492 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001493 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001494 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001495xmlChar *
1496xmlStrndup(const xmlChar *cur, int len) {
1497 xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001498
1499 if (ret == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001500 fprintf(stderr, "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001501 (len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001502 return(NULL);
1503 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001504 memcpy(ret, cur, len * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001505 ret[len] = 0;
1506 return(ret);
1507}
1508
Daniel Veillard11e00581998-10-24 18:27:49 +00001509/**
1510 * xmlStrdup:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001511 * @cur: the input xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001512 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001513 * a strdup for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001514 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001515 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001516 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001517xmlChar *
1518xmlStrdup(const xmlChar *cur) {
1519 const xmlChar *p = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001520
1521 while (IS_CHAR(*p)) p++;
1522 return(xmlStrndup(cur, p - cur));
1523}
1524
Daniel Veillard11e00581998-10-24 18:27:49 +00001525/**
1526 * xmlCharStrndup:
1527 * @cur: the input char *
1528 * @len: the len of @cur
1529 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001530 * a strndup for char's to xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001531 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001532 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001533 */
1534
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001535xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001536xmlCharStrndup(const char *cur, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001537 int i;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001538 xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001539
1540 if (ret == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001541 fprintf(stderr, "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001542 (len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001543 return(NULL);
1544 }
1545 for (i = 0;i < len;i++)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001546 ret[i] = (xmlChar) cur[i];
Daniel Veillard260a68f1998-08-13 03:39:55 +00001547 ret[len] = 0;
1548 return(ret);
1549}
1550
Daniel Veillard11e00581998-10-24 18:27:49 +00001551/**
1552 * xmlCharStrdup:
1553 * @cur: the input char *
1554 * @len: the len of @cur
1555 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001556 * a strdup for char's to xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001557 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001558 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001559 */
1560
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001561xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001562xmlCharStrdup(const char *cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001563 const char *p = cur;
1564
1565 while (*p != '\0') p++;
1566 return(xmlCharStrndup(cur, p - cur));
1567}
1568
Daniel Veillard11e00581998-10-24 18:27:49 +00001569/**
1570 * xmlStrcmp:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001571 * @str1: the first xmlChar *
1572 * @str2: the second xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001573 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001574 * a strcmp for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001575 *
1576 * Returns the integer result of the comparison
Daniel Veillard260a68f1998-08-13 03:39:55 +00001577 */
1578
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001579int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001580xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581 register int tmp;
1582
1583 do {
1584 tmp = *str1++ - *str2++;
1585 if (tmp != 0) return(tmp);
1586 } while ((*str1 != 0) && (*str2 != 0));
1587 return (*str1 - *str2);
1588}
1589
Daniel Veillard11e00581998-10-24 18:27:49 +00001590/**
1591 * xmlStrncmp:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001592 * @str1: the first xmlChar *
1593 * @str2: the second xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001594 * @len: the max comparison length
1595 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001596 * a strncmp for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001597 *
1598 * Returns the integer result of the comparison
Daniel Veillard260a68f1998-08-13 03:39:55 +00001599 */
1600
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001601int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001602xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001603 register int tmp;
1604
1605 if (len <= 0) return(0);
1606 do {
1607 tmp = *str1++ - *str2++;
1608 if (tmp != 0) return(tmp);
1609 len--;
1610 if (len <= 0) return(0);
1611 } while ((*str1 != 0) && (*str2 != 0));
1612 return (*str1 - *str2);
1613}
1614
Daniel Veillard11e00581998-10-24 18:27:49 +00001615/**
1616 * xmlStrchr:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001617 * @str: the xmlChar * array
1618 * @val: the xmlChar to search
Daniel Veillard11e00581998-10-24 18:27:49 +00001619 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001620 * a strchr for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001621 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001622 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001623 */
1624
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001625const xmlChar *
1626xmlStrchr(const xmlChar *str, xmlChar val) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001627 while (*str != 0) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001628 if (*str == val) return((xmlChar *) str);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001629 str++;
1630 }
1631 return(NULL);
1632}
1633
Daniel Veillard11e00581998-10-24 18:27:49 +00001634/**
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001635 * xmlStrstr:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001636 * @str: the xmlChar * array (haystack)
1637 * @val: the xmlChar to search (needle)
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001638 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001639 * a strstr for xmlChar's
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001640 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001641 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001642 */
1643
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001644const xmlChar *
1645xmlStrstr(const xmlChar *str, xmlChar *val) {
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001646 int n;
1647
1648 if (str == NULL) return(NULL);
1649 if (val == NULL) return(NULL);
1650 n = xmlStrlen(val);
1651
1652 if (n == 0) return(str);
1653 while (*str != 0) {
1654 if (*str == *val) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001655 if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001656 }
1657 str++;
1658 }
1659 return(NULL);
1660}
1661
1662/**
1663 * xmlStrsub:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001664 * @str: the xmlChar * array (haystack)
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001665 * @start: the index of the first char (zero based)
1666 * @len: the length of the substring
1667 *
1668 * Extract a substring of a given string
1669 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001670 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001671 */
1672
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001673xmlChar *
1674xmlStrsub(const xmlChar *str, int start, int len) {
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001675 int i;
1676
1677 if (str == NULL) return(NULL);
1678 if (start < 0) return(NULL);
1679 if (len < 0) return(NULL);
1680
1681 for (i = 0;i < start;i++) {
1682 if (*str == 0) return(NULL);
1683 str++;
1684 }
1685 if (*str == 0) return(NULL);
1686 return(xmlStrndup(str, len));
1687}
1688
1689/**
Daniel Veillard11e00581998-10-24 18:27:49 +00001690 * xmlStrlen:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001691 * @str: the xmlChar * array
Daniel Veillard11e00581998-10-24 18:27:49 +00001692 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001693 * lenght of a xmlChar's string
Daniel Veillard1e346af1999-02-22 10:33:01 +00001694 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001695 * Returns the number of xmlChar contained in the ARRAY.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001696 */
1697
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001698int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001699xmlStrlen(const xmlChar *str) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001700 int len = 0;
1701
1702 if (str == NULL) return(0);
1703 while (*str != 0) {
1704 str++;
1705 len++;
1706 }
1707 return(len);
1708}
1709
Daniel Veillard11e00581998-10-24 18:27:49 +00001710/**
1711 * xmlStrncat:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001712 * @cur: the original xmlChar * array
1713 * @add: the xmlChar * array added
Daniel Veillard11e00581998-10-24 18:27:49 +00001714 * @len: the length of @add
1715 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001716 * a strncat for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001717 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001718 * Returns a new xmlChar * containing the concatenated string.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001719 */
1720
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001721xmlChar *
1722xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001723 int size;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001724 xmlChar *ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001725
1726 if ((add == NULL) || (len == 0))
1727 return(cur);
1728 if (cur == NULL)
1729 return(xmlStrndup(add, len));
1730
1731 size = xmlStrlen(cur);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001732 ret = xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001733 if (ret == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001734 fprintf(stderr, "xmlStrncat: realloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001735 (size + len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001736 return(cur);
1737 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001738 memcpy(&ret[size], add, len * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001739 ret[size + len] = 0;
1740 return(ret);
1741}
1742
Daniel Veillard11e00581998-10-24 18:27:49 +00001743/**
1744 * xmlStrcat:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001745 * @cur: the original xmlChar * array
1746 * @add: the xmlChar * array added
Daniel Veillard11e00581998-10-24 18:27:49 +00001747 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001748 * a strcat for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001749 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001750 * Returns a new xmlChar * containing the concatenated string.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001751 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001752xmlChar *
1753xmlStrcat(xmlChar *cur, const xmlChar *add) {
1754 const xmlChar *p = add;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001755
1756 if (add == NULL) return(cur);
1757 if (cur == NULL)
1758 return(xmlStrdup(add));
1759
1760 while (IS_CHAR(*p)) p++;
1761 return(xmlStrncat(cur, add, p - add));
1762}
1763
1764/************************************************************************
1765 * *
1766 * Commodity functions, cleanup needed ? *
1767 * *
1768 ************************************************************************/
1769
Daniel Veillard11e00581998-10-24 18:27:49 +00001770/**
1771 * areBlanks:
1772 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001773 * @str: a xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001774 * @len: the size of @str
1775 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001776 * Is this a sequence of blank chars that one can ignore ?
Daniel Veillard11e00581998-10-24 18:27:49 +00001777 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00001778 * TODO: Whether white space are significant has to be checked accordingly
1779 * to DTD informations if available
Daniel Veillard1e346af1999-02-22 10:33:01 +00001780 *
1781 * Returns 1 if ignorable 0 otherwise.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001782 */
1783
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001784static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001785 int i, ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001786 xmlNodePtr lastChild;
1787
1788 for (i = 0;i < len;i++)
1789 if (!(IS_BLANK(str[i]))) return(0);
1790
1791 if (CUR != '<') return(0);
Daniel Veillard517752b1999-04-05 12:20:10 +00001792 if (ctxt->node == NULL) return(0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001793 if (ctxt->myDoc != NULL) {
1794 ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
1795 if (ret == 0) return(1);
1796 if (ret == 1) return(0);
1797 }
1798 /*
1799 * heuristic
1800 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001801 lastChild = xmlGetLastChild(ctxt->node);
1802 if (lastChild == NULL) {
1803 if (ctxt->node->content != NULL) return(0);
1804 } else if (xmlNodeIsText(lastChild))
1805 return(0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001806 else if ((ctxt->node->childs != NULL) &&
1807 (xmlNodeIsText(ctxt->node->childs)))
1808 return(0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001809 return(1);
1810}
1811
Daniel Veillard11e00581998-10-24 18:27:49 +00001812/**
1813 * xmlHandleEntity:
1814 * @ctxt: an XML parser context
1815 * @entity: an XML entity pointer.
1816 *
1817 * Default handling of defined entities, when should we define a new input
Daniel Veillard260a68f1998-08-13 03:39:55 +00001818 * stream ? When do we just handle that as a set of chars ?
Daniel Veillardb05deb71999-08-10 19:04:08 +00001819 *
1820 * OBSOLETE: to be removed at some point.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001821 */
1822
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001823void
1824xmlHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001825 int len;
Daniel Veillardccb09631998-10-27 06:21:04 +00001826 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001827
1828 if (entity->content == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001829 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00001830 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00001831 ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
Daniel Veillard260a68f1998-08-13 03:39:55 +00001832 entity->name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001833 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001834 return;
1835 }
1836 len = xmlStrlen(entity->content);
1837 if (len <= 2) goto handle_as_char;
1838
1839 /*
1840 * Redefine its content as an input stream.
1841 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001842 input = xmlNewEntityInputStream(ctxt, entity);
1843 xmlPushInput(ctxt, input);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001844 return;
1845
1846handle_as_char:
1847 /*
1848 * Just handle the content as a set of chars.
1849 */
Daniel Veillard517752b1999-04-05 12:20:10 +00001850 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00001851 ctxt->sax->characters(ctxt->userData, entity->content, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001852
1853}
1854
1855/*
1856 * Forward definition for recusive behaviour.
1857 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00001858void xmlParsePEReference(xmlParserCtxtPtr ctxt);
1859void xmlParseReference(xmlParserCtxtPtr ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001860
1861/************************************************************************
1862 * *
1863 * Extra stuff for namespace support *
1864 * Relates to http://www.w3.org/TR/WD-xml-names *
1865 * *
1866 ************************************************************************/
1867
Daniel Veillard11e00581998-10-24 18:27:49 +00001868/**
1869 * xmlNamespaceParseNCName:
1870 * @ctxt: an XML parser context
1871 *
1872 * parse an XML namespace name.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001873 *
1874 * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
1875 *
1876 * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
1877 * CombiningChar | Extender
Daniel Veillard1e346af1999-02-22 10:33:01 +00001878 *
1879 * Returns the namespace name or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001880 */
1881
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001882xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001883xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001884 xmlChar buf[XML_MAX_NAMELEN];
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001885 int len = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001886
1887 if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001888
1889 while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1890 (CUR == '.') || (CUR == '-') ||
1891 (CUR == '_') ||
1892 (IS_COMBINING(CUR)) ||
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001893 (IS_EXTENDER(CUR))) {
1894 buf[len++] = CUR;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001895 NEXT;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001896 if (len >= XML_MAX_NAMELEN) {
1897 fprintf(stderr,
1898 "xmlNamespaceParseNCName: reached XML_MAX_NAMELEN limit\n");
1899 while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1900 (CUR == '.') || (CUR == '-') ||
1901 (CUR == '_') ||
1902 (IS_COMBINING(CUR)) ||
1903 (IS_EXTENDER(CUR)))
1904 NEXT;
1905 break;
1906 }
1907 }
1908 return(xmlStrndup(buf, len));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001909}
1910
Daniel Veillard11e00581998-10-24 18:27:49 +00001911/**
1912 * xmlNamespaceParseQName:
1913 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001914 * @prefix: a xmlChar **
Daniel Veillard11e00581998-10-24 18:27:49 +00001915 *
1916 * parse an XML qualified name
Daniel Veillard260a68f1998-08-13 03:39:55 +00001917 *
1918 * [NS 5] QName ::= (Prefix ':')? LocalPart
1919 *
1920 * [NS 6] Prefix ::= NCName
1921 *
1922 * [NS 7] LocalPart ::= NCName
Daniel Veillard1e346af1999-02-22 10:33:01 +00001923 *
1924 * Returns the function returns the local part, and prefix is updated
Daniel Veillard11e00581998-10-24 18:27:49 +00001925 * to get the Prefix if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001926 */
1927
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001928xmlChar *
1929xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, xmlChar **prefix) {
1930 xmlChar *ret = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001931
1932 *prefix = NULL;
1933 ret = xmlNamespaceParseNCName(ctxt);
1934 if (CUR == ':') {
1935 *prefix = ret;
1936 NEXT;
1937 ret = xmlNamespaceParseNCName(ctxt);
1938 }
1939
1940 return(ret);
1941}
1942
Daniel Veillard11e00581998-10-24 18:27:49 +00001943/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001944 * xmlSplitQName:
1945 * @name: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001946 * @prefix: a xmlChar **
Daniel Veillard517752b1999-04-05 12:20:10 +00001947 *
1948 * parse an XML qualified name string
1949 *
1950 * [NS 5] QName ::= (Prefix ':')? LocalPart
1951 *
1952 * [NS 6] Prefix ::= NCName
1953 *
1954 * [NS 7] LocalPart ::= NCName
1955 *
1956 * Returns the function returns the local part, and prefix is updated
1957 * to get the Prefix if any.
1958 */
1959
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001960xmlChar *
1961xmlSplitQName(const xmlChar *name, xmlChar **prefix) {
1962 xmlChar *ret = NULL;
1963 const xmlChar *q;
1964 const xmlChar *cur = name;
Daniel Veillard517752b1999-04-05 12:20:10 +00001965
1966 *prefix = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001967
1968 /* xml: prefix is not really a namespace */
1969 if ((cur[0] == 'x') && (cur[1] == 'm') &&
1970 (cur[2] == 'l') && (cur[3] == ':'))
1971 return(xmlStrdup(name));
1972
Daniel Veillard517752b1999-04-05 12:20:10 +00001973 if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL);
1974 q = cur++;
1975
1976 while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
1977 (*cur == '.') || (*cur == '-') ||
1978 (*cur == '_') ||
1979 (IS_COMBINING(*cur)) ||
1980 (IS_EXTENDER(*cur)))
1981 cur++;
1982
1983 ret = xmlStrndup(q, cur - q);
1984
1985 if (*cur == ':') {
1986 cur++;
1987 if (!IS_LETTER(*cur) && (*cur != '_')) return(ret);
1988 *prefix = ret;
1989
1990 q = cur++;
1991
1992 while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
1993 (*cur == '.') || (*cur == '-') ||
1994 (*cur == '_') ||
1995 (IS_COMBINING(*cur)) ||
1996 (IS_EXTENDER(*cur)))
1997 cur++;
1998
1999 ret = xmlStrndup(q, cur - q);
2000 }
2001
2002 return(ret);
2003}
2004/**
Daniel Veillard11e00581998-10-24 18:27:49 +00002005 * xmlNamespaceParseNSDef:
2006 * @ctxt: an XML parser context
2007 *
2008 * parse a namespace prefix declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00002009 *
2010 * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral
2011 *
2012 * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002013 *
2014 * Returns the namespace name
Daniel Veillard260a68f1998-08-13 03:39:55 +00002015 */
2016
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002017xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002018xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002019 xmlChar *name = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002020
2021 if ((CUR == 'x') && (NXT(1) == 'm') &&
2022 (NXT(2) == 'l') && (NXT(3) == 'n') &&
2023 (NXT(4) == 's')) {
2024 SKIP(5);
2025 if (CUR == ':') {
2026 NEXT;
2027 name = xmlNamespaceParseNCName(ctxt);
2028 }
2029 }
2030 return(name);
2031}
2032
Daniel Veillard11e00581998-10-24 18:27:49 +00002033/**
2034 * xmlParseQuotedString:
2035 * @ctxt: an XML parser context
2036 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002037 * [OLD] Parse and return a string between quotes or doublequotes
Daniel Veillardb05deb71999-08-10 19:04:08 +00002038 * To be removed at next drop of binary compatibility
Daniel Veillard1e346af1999-02-22 10:33:01 +00002039 *
2040 * Returns the string parser or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002041 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002042xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002043xmlParseQuotedString(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002044 xmlChar *ret = NULL;
2045 const xmlChar *q;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002046
2047 if (CUR == '"') {
2048 NEXT;
2049 q = CUR_PTR;
2050 while (IS_CHAR(CUR) && (CUR != '"')) NEXT;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002051 if (CUR != '"') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002052 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002053 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002054 ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002055 ctxt->wellFormed = 0;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002056 } else {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002057 ret = xmlStrndup(q, CUR_PTR - q);
2058 NEXT;
2059 }
2060 } else if (CUR == '\''){
2061 NEXT;
2062 q = CUR_PTR;
2063 while (IS_CHAR(CUR) && (CUR != '\'')) NEXT;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002064 if (CUR != '\'') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002065 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002066 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002067 ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002068 ctxt->wellFormed = 0;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002069 } else {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002070 ret = xmlStrndup(q, CUR_PTR - q);
2071 NEXT;
2072 }
2073 }
2074 return(ret);
2075}
2076
Daniel Veillard11e00581998-10-24 18:27:49 +00002077/**
2078 * xmlParseNamespace:
2079 * @ctxt: an XML parser context
2080 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002081 * [OLD] xmlParseNamespace: parse specific PI '<?namespace ...' constructs.
2082 *
2083 * This is what the older xml-name Working Draft specified, a bunch of
2084 * other stuff may still rely on it, so support is still here as
2085 * if ot was declared on the root of the Tree:-(
Daniel Veillardb05deb71999-08-10 19:04:08 +00002086 *
2087 * To be removed at next drop of binary compatibility
Daniel Veillard260a68f1998-08-13 03:39:55 +00002088 */
2089
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002090void
2091xmlParseNamespace(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002092 xmlChar *href = NULL;
2093 xmlChar *prefix = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002094 int garbage = 0;
2095
2096 /*
2097 * We just skipped "namespace" or "xml:namespace"
2098 */
2099 SKIP_BLANKS;
2100
2101 while (IS_CHAR(CUR) && (CUR != '>')) {
2102 /*
2103 * We can have "ns" or "prefix" attributes
2104 * Old encoding as 'href' or 'AS' attributes is still supported
2105 */
2106 if ((CUR == 'n') && (NXT(1) == 's')) {
2107 garbage = 0;
2108 SKIP(2);
2109 SKIP_BLANKS;
2110
2111 if (CUR != '=') continue;
2112 NEXT;
2113 SKIP_BLANKS;
2114
2115 href = xmlParseQuotedString(ctxt);
2116 SKIP_BLANKS;
2117 } else if ((CUR == 'h') && (NXT(1) == 'r') &&
2118 (NXT(2) == 'e') && (NXT(3) == 'f')) {
2119 garbage = 0;
2120 SKIP(4);
2121 SKIP_BLANKS;
2122
2123 if (CUR != '=') continue;
2124 NEXT;
2125 SKIP_BLANKS;
2126
2127 href = xmlParseQuotedString(ctxt);
2128 SKIP_BLANKS;
2129 } else if ((CUR == 'p') && (NXT(1) == 'r') &&
2130 (NXT(2) == 'e') && (NXT(3) == 'f') &&
2131 (NXT(4) == 'i') && (NXT(5) == 'x')) {
2132 garbage = 0;
2133 SKIP(6);
2134 SKIP_BLANKS;
2135
2136 if (CUR != '=') continue;
2137 NEXT;
2138 SKIP_BLANKS;
2139
2140 prefix = xmlParseQuotedString(ctxt);
2141 SKIP_BLANKS;
2142 } else if ((CUR == 'A') && (NXT(1) == 'S')) {
2143 garbage = 0;
2144 SKIP(2);
2145 SKIP_BLANKS;
2146
2147 if (CUR != '=') continue;
2148 NEXT;
2149 SKIP_BLANKS;
2150
2151 prefix = xmlParseQuotedString(ctxt);
2152 SKIP_BLANKS;
2153 } else if ((CUR == '?') && (NXT(1) == '>')) {
2154 garbage = 0;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002155 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002156 } else {
2157 /*
2158 * Found garbage when parsing the namespace
2159 */
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002160 if (!garbage) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002161 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002162 ctxt->sax->error(ctxt->userData,
2163 "xmlParseNamespace found garbage\n");
2164 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002165 ctxt->errNo = XML_ERR_NS_DECL_ERROR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002166 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002167 NEXT;
2168 }
2169 }
2170
2171 MOVETO_ENDTAG(CUR_PTR);
2172 NEXT;
2173
2174 /*
2175 * Register the DTD.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002176 if (href != NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +00002177 if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002178 ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +00002179 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002180
Daniel Veillard6454aec1999-09-02 22:04:43 +00002181 if (prefix != NULL) xmlFree(prefix);
2182 if (href != NULL) xmlFree(href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002183}
2184
2185/************************************************************************
2186 * *
2187 * The parser itself *
2188 * Relates to http://www.w3.org/TR/REC-xml *
2189 * *
2190 ************************************************************************/
2191
Daniel Veillard11e00581998-10-24 18:27:49 +00002192/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00002193 * xmlScanName:
2194 * @ctxt: an XML parser context
2195 *
2196 * Trickery: parse an XML name but without consuming the input flow
2197 * Needed for rollback cases.
2198 *
2199 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
2200 * CombiningChar | Extender
2201 *
2202 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
2203 *
2204 * [6] Names ::= Name (S Name)*
2205 *
2206 * Returns the Name parsed or NULL
2207 */
2208
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002209xmlChar *
Daniel Veillardb05deb71999-08-10 19:04:08 +00002210xmlScanName(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002211 xmlChar buf[XML_MAX_NAMELEN];
Daniel Veillardb05deb71999-08-10 19:04:08 +00002212 int len = 0;
2213
2214 GROW;
2215 if (!IS_LETTER(CUR) && (CUR != '_') &&
2216 (CUR != ':')) {
2217 return(NULL);
2218 }
2219
2220 while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
2221 (NXT(len) == '.') || (NXT(len) == '-') ||
2222 (NXT(len) == '_') || (NXT(len) == ':') ||
2223 (IS_COMBINING(NXT(len))) ||
2224 (IS_EXTENDER(NXT(len)))) {
2225 buf[len] = NXT(len);
2226 len++;
2227 if (len >= XML_MAX_NAMELEN) {
2228 fprintf(stderr,
2229 "xmlScanName: reached XML_MAX_NAMELEN limit\n");
2230 while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
2231 (NXT(len) == '.') || (NXT(len) == '-') ||
2232 (NXT(len) == '_') || (NXT(len) == ':') ||
2233 (IS_COMBINING(NXT(len))) ||
2234 (IS_EXTENDER(NXT(len))))
2235 len++;
2236 break;
2237 }
2238 }
2239 return(xmlStrndup(buf, len));
2240}
2241
2242/**
Daniel Veillard11e00581998-10-24 18:27:49 +00002243 * xmlParseName:
2244 * @ctxt: an XML parser context
2245 *
2246 * parse an XML name.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002247 *
2248 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
2249 * CombiningChar | Extender
2250 *
2251 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
2252 *
2253 * [6] Names ::= Name (S Name)*
Daniel Veillard1e346af1999-02-22 10:33:01 +00002254 *
2255 * Returns the Name parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002256 */
2257
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002258xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002259xmlParseName(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002260 xmlChar buf[XML_MAX_NAMELEN];
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002261 int len = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002262 xmlChar cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002263
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002264 GROW;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002265 cur = CUR;
2266 if (!IS_LETTER(cur) && (cur != '_') &&
2267 (cur != ':')) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002268 return(NULL);
2269 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002270
Daniel Veillardb05deb71999-08-10 19:04:08 +00002271 while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2272 (cur == '.') || (cur == '-') ||
2273 (cur == '_') || (cur == ':') ||
2274 (IS_COMBINING(cur)) ||
2275 (IS_EXTENDER(cur))) {
2276 buf[len++] = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002277 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002278 cur = CUR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002279 if (len >= XML_MAX_NAMELEN) {
2280 fprintf(stderr,
2281 "xmlParseName: reached XML_MAX_NAMELEN limit\n");
Daniel Veillardb05deb71999-08-10 19:04:08 +00002282 while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2283 (cur == '.') || (cur == '-') ||
2284 (cur == '_') || (cur == ':') ||
2285 (IS_COMBINING(cur)) ||
2286 (IS_EXTENDER(cur))) {
2287 NEXT;
2288 cur = CUR;
2289 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002290 break;
2291 }
2292 }
2293 return(xmlStrndup(buf, len));
Daniel Veillard260a68f1998-08-13 03:39:55 +00002294}
2295
Daniel Veillard11e00581998-10-24 18:27:49 +00002296/**
2297 * xmlParseNmtoken:
2298 * @ctxt: an XML parser context
2299 *
2300 * parse an XML Nmtoken.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002301 *
2302 * [7] Nmtoken ::= (NameChar)+
2303 *
2304 * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
Daniel Veillard1e346af1999-02-22 10:33:01 +00002305 *
2306 * Returns the Nmtoken parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002307 */
2308
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002309xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002310xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002311 xmlChar buf[XML_MAX_NAMELEN];
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002312 int len = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002313
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002314 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002315 while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2316 (CUR == '.') || (CUR == '-') ||
2317 (CUR == '_') || (CUR == ':') ||
2318 (IS_COMBINING(CUR)) ||
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002319 (IS_EXTENDER(CUR))) {
2320 buf[len++] = CUR;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002321 NEXT;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002322 if (len >= XML_MAX_NAMELEN) {
2323 fprintf(stderr,
2324 "xmlParseNmtoken: reached XML_MAX_NAMELEN limit\n");
2325 while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2326 (CUR == '.') || (CUR == '-') ||
2327 (CUR == '_') || (CUR == ':') ||
2328 (IS_COMBINING(CUR)) ||
2329 (IS_EXTENDER(CUR)))
2330 NEXT;
2331 break;
2332 }
2333 }
2334 return(xmlStrndup(buf, len));
Daniel Veillard260a68f1998-08-13 03:39:55 +00002335}
2336
Daniel Veillard11e00581998-10-24 18:27:49 +00002337/**
2338 * xmlParseEntityValue:
2339 * @ctxt: an XML parser context
Daniel Veillard011b63c1999-06-02 17:44:04 +00002340 * @orig: if non-NULL store a copy of the original entity value
Daniel Veillard11e00581998-10-24 18:27:49 +00002341 *
2342 * parse a value for ENTITY decl.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002343 *
2344 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
2345 * "'" ([^%&'] | PEReference | Reference)* "'"
Daniel Veillard1e346af1999-02-22 10:33:01 +00002346 *
Daniel Veillard011b63c1999-06-02 17:44:04 +00002347 * Returns the EntityValue parsed with reference substitued or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002348 */
2349
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002350xmlChar *
2351xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
2352 xmlChar *ret = NULL;
2353 const xmlChar *org = NULL;
2354 const xmlChar *tst = NULL;
2355 const xmlChar *temp = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002356 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002357
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002358 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002359 if (CUR == '"') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002360 ctxt->instate = XML_PARSER_ENTITY_VALUE;
2361 input = ctxt->input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002362 NEXT;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002363 org = CUR_PTR;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002364 /*
2365 * NOTE: 4.4.5 Included in Literal
2366 * When a parameter entity reference appears in a literal entity
2367 * value, ... a single or double quote character in the replacement
2368 * text is always treated as a normal data character and will not
2369 * terminate the literal.
2370 * In practice it means we stop the loop only when back at parsing
2371 * the initial entity and the quote is found
2372 */
2373 while ((CUR != '"') || (ctxt->input != input)) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002374 tst = CUR_PTR;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002375 /*
2376 * NOTE: 4.4.7 Bypassed
2377 * When a general entity reference appears in the EntityValue in
2378 * an entity declaration, it is bypassed and left as is.
2379 * so XML_SUBSTITUTE_REF is not set.
2380 */
2381 if (ctxt->input != input)
2382 temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2383 0, 0, 0);
2384 else
2385 temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2386 '"', 0, 0);
2387
2388 /*
2389 * Pop-up of finished entities.
2390 */
2391 while ((CUR == 0) && (ctxt->inputNr > 1))
2392 xmlPopInput(ctxt);
2393
2394 if ((temp == NULL) && (tst == CUR_PTR)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002395 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002396 break;
2397 }
2398 if ((temp[0] == 0) && (tst == CUR_PTR)) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002399 xmlFree((char *)temp);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002400 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002401 break;
2402 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00002403 ret = xmlStrcat(ret, temp);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002404 if (temp != NULL) xmlFree((char *)temp);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002405 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002406 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00002407 if (CUR != '"') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002408 ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002409 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00002410 ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002411 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002412 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002413 if (orig != NULL) /* !!!!!!!!! */
Daniel Veillard011b63c1999-06-02 17:44:04 +00002414 *orig = xmlStrndup(org, CUR_PTR - org);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002415 if (ret == NULL)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002416 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002417 NEXT;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002418 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002419 } else if (CUR == '\'') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002420 ctxt->instate = XML_PARSER_ENTITY_VALUE;
2421 input = ctxt->input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002422 NEXT;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002423 org = CUR_PTR;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002424 /*
2425 * NOTE: 4.4.5 Included in Literal
2426 * When a parameter entity reference appears in a literal entity
2427 * value, ... a single or double quote character in the replacement
2428 * text is always treated as a normal data character and will not
2429 * terminate the literal.
2430 * In practice it means we stop the loop only when back at parsing
2431 * the initial entity and the quote is found
2432 */
2433 while ((CUR != '\'') || (ctxt->input != input)) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002434 tst = CUR_PTR;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002435 /*
2436 * NOTE: 4.4.7 Bypassed
2437 * When a general entity reference appears in the EntityValue in
2438 * an entity declaration, it is bypassed and left as is.
2439 * so XML_SUBSTITUTE_REF is not set.
2440 */
2441 if (ctxt->input != input)
2442 temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2443 0, 0, 0);
2444 else
2445 temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2446 '\'', 0, 0);
2447
2448 /*
2449 * Pop-up of finished entities.
2450 */
2451 while ((CUR == 0) && (ctxt->inputNr > 1))
2452 xmlPopInput(ctxt);
2453
2454 if ((temp == NULL) && (tst == CUR_PTR)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002455 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002456 break;
2457 }
2458 if ((temp[0] == 0) && (tst == CUR_PTR)) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002459 xmlFree((char *)temp);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002460 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002461 break;
2462 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00002463 ret = xmlStrcat(ret, temp);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002464 if (temp != NULL) xmlFree((char *)temp);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002465 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002466 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00002467 if (CUR != '\'') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002468 ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002469 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00002470 ctxt->sax->error(ctxt->userData, "EntityValue: ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002471 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002472 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002473 if (orig != NULL) /* !!!!!!!!! */
Daniel Veillard011b63c1999-06-02 17:44:04 +00002474 *orig = xmlStrndup(org, CUR_PTR - org);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002475 if (ret == NULL)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002476 ret = xmlStrndup((xmlChar *) "", 0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002477 NEXT;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002478 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002479 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002480 ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002481 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00002482 ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002483 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002484 }
2485
2486 return(ret);
2487}
2488
Daniel Veillard11e00581998-10-24 18:27:49 +00002489/**
2490 * xmlParseAttValue:
2491 * @ctxt: an XML parser context
2492 *
2493 * parse a value for an attribute
Daniel Veillard011b63c1999-06-02 17:44:04 +00002494 * Note: the parser won't do substitution of entities here, this
Daniel Veillardb96e6431999-08-29 21:02:19 +00002495 * will be handled later in xmlStringGetNodeList
Daniel Veillard260a68f1998-08-13 03:39:55 +00002496 *
2497 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
2498 * "'" ([^<&'] | Reference)* "'"
Daniel Veillard1e346af1999-02-22 10:33:01 +00002499 *
2500 * Returns the AttValue parsed or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002501 */
2502
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002503xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002504xmlParseAttValue(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002505 xmlChar *ret = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002506
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002507 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002508 if (CUR == '"') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002509 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002510 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002511 ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_REF, '"', '<', 0);
Daniel Veillard011b63c1999-06-02 17:44:04 +00002512 if (CUR == '<') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002513 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00002514 ctxt->sax->error(ctxt->userData,
2515 "Unescaped '<' not allowed in attributes values\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002516 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002517 ctxt->wellFormed = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002518 }
2519 if (CUR != '"') {
2520 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2521 ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002522 ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002523 ctxt->wellFormed = 0;
2524 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00002525 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002526 } else if (CUR == '\'') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002527 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002528 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002529 ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_REF, '\'', '<', 0);
Daniel Veillard011b63c1999-06-02 17:44:04 +00002530 if (CUR == '<') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002531 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00002532 ctxt->sax->error(ctxt->userData,
2533 "Unescaped '<' not allowed in attributes values\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002534 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002535 ctxt->wellFormed = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002536 }
2537 if (CUR != '\'') {
2538 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2539 ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002540 ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00002541 ctxt->wellFormed = 0;
2542 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00002543 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002544 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002545 ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002546 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002547 ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002548 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002549 }
2550
2551 return(ret);
2552}
2553
Daniel Veillard11e00581998-10-24 18:27:49 +00002554/**
2555 * xmlParseSystemLiteral:
2556 * @ctxt: an XML parser context
2557 *
2558 * parse an XML Literal
Daniel Veillard260a68f1998-08-13 03:39:55 +00002559 *
2560 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
Daniel Veillard1e346af1999-02-22 10:33:01 +00002561 *
2562 * Returns the SystemLiteral parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002563 */
2564
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002565xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002566xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002567 const xmlChar *q;
2568 xmlChar *ret = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002569
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002570 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002571 if (CUR == '"') {
2572 NEXT;
2573 q = CUR_PTR;
2574 while ((IS_CHAR(CUR)) && (CUR != '"'))
2575 NEXT;
2576 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002577 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002578 ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002579 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002580 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002581 } else {
2582 ret = xmlStrndup(q, CUR_PTR - q);
2583 NEXT;
2584 }
2585 } else if (CUR == '\'') {
2586 NEXT;
2587 q = CUR_PTR;
2588 while ((IS_CHAR(CUR)) && (CUR != '\''))
2589 NEXT;
2590 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002591 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002592 ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002593 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002594 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002595 } else {
2596 ret = xmlStrndup(q, CUR_PTR - q);
2597 NEXT;
2598 }
2599 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002600 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002601 ctxt->sax->error(ctxt->userData,
2602 "SystemLiteral \" or ' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002603 ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002604 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002605 }
2606
2607 return(ret);
2608}
2609
Daniel Veillard11e00581998-10-24 18:27:49 +00002610/**
2611 * xmlParsePubidLiteral:
2612 * @ctxt: an XML parser context
Daniel Veillard260a68f1998-08-13 03:39:55 +00002613 *
Daniel Veillard11e00581998-10-24 18:27:49 +00002614 * parse an XML public literal
Daniel Veillard1e346af1999-02-22 10:33:01 +00002615 *
2616 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2617 *
2618 * Returns the PubidLiteral parsed or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002619 */
2620
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002621xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002622xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002623 const xmlChar *q;
2624 xmlChar *ret = NULL;
Daniel Veillard6077d031999-10-09 09:11:45 +00002625
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002626 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002627 if (CUR == '"') {
2628 NEXT;
2629 q = CUR_PTR;
2630 while (IS_PUBIDCHAR(CUR)) NEXT;
2631 if (CUR != '"') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002632 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002633 ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002634 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002635 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002636 } else {
2637 ret = xmlStrndup(q, CUR_PTR - q);
2638 NEXT;
2639 }
2640 } else if (CUR == '\'') {
2641 NEXT;
2642 q = CUR_PTR;
Daniel Veillard6077d031999-10-09 09:11:45 +00002643 while (IS_PUBIDCHAR(CUR)) NEXT;
2644 if (CUR != '\'') {
2645 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002646 ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002647 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002648 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002649 } else {
2650 ret = xmlStrndup(q, CUR_PTR - q);
2651 NEXT;
2652 }
2653 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002654 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002655 ctxt->sax->error(ctxt->userData,
2656 "SystemLiteral \" or ' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002657 ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002658 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002659 }
2660
2661 return(ret);
2662}
2663
Daniel Veillard11e00581998-10-24 18:27:49 +00002664/**
2665 * xmlParseCharData:
2666 * @ctxt: an XML parser context
2667 * @cdata: int indicating whether we are within a CDATA section
2668 *
2669 * parse a CharData section.
2670 * if we are within a CDATA section ']]>' marks an end of section.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002671 *
2672 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2673 */
2674
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002675void
2676xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002677 xmlChar buf[1000];
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002678 int nbchar = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002679 xmlChar cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002680
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002681 SHRINK;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002682 /*
2683 * !!!!!!!!!!!!
2684 * NOTE: NXT(0) is used here to avoid breaking on &lt; or &amp;
2685 * entities substitutions.
2686 */
2687 cur = CUR;
2688 while ((IS_CHAR(cur)) && (cur != '<') &&
2689 (cur != '&')) {
2690 if ((cur == ']') && (NXT(1) == ']') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002691 (NXT(2) == '>')) {
2692 if (cdata) break;
2693 else {
2694 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002695 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002696 "Sequence ']]>' not allowed in content\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002697 ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002698 ctxt->wellFormed = 0;
2699 }
2700 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002701 buf[nbchar++] = CUR;
2702 if (nbchar == 1000) {
2703 /*
2704 * Ok the segment is to be consumed as chars.
2705 */
2706 if (ctxt->sax != NULL) {
2707 if (areBlanks(ctxt, buf, nbchar)) {
2708 if (ctxt->sax->ignorableWhitespace != NULL)
2709 ctxt->sax->ignorableWhitespace(ctxt->userData,
2710 buf, nbchar);
2711 } else {
2712 if (ctxt->sax->characters != NULL)
2713 ctxt->sax->characters(ctxt->userData, buf, nbchar);
2714 }
2715 }
2716 nbchar = 0;
2717 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002718 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002719 cur = CUR;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002720 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002721 if (nbchar != 0) {
2722 /*
2723 * Ok the segment is to be consumed as chars.
2724 */
2725 if (ctxt->sax != NULL) {
2726 if (areBlanks(ctxt, buf, nbchar)) {
2727 if (ctxt->sax->ignorableWhitespace != NULL)
2728 ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2729 } else {
2730 if (ctxt->sax->characters != NULL)
2731 ctxt->sax->characters(ctxt->userData, buf, nbchar);
2732 }
2733 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002734 }
2735}
2736
Daniel Veillard11e00581998-10-24 18:27:49 +00002737/**
2738 * xmlParseExternalID:
2739 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002740 * @publicID: a xmlChar** receiving PubidLiteral
Daniel Veillard1e346af1999-02-22 10:33:01 +00002741 * @strict: indicate whether we should restrict parsing to only
2742 * production [75], see NOTE below
Daniel Veillard11e00581998-10-24 18:27:49 +00002743 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002744 * Parse an External ID or a Public ID
2745 *
2746 * NOTE: Productions [75] and [83] interract badly since [75] can generate
2747 * 'PUBLIC' S PubidLiteral S SystemLiteral
Daniel Veillard260a68f1998-08-13 03:39:55 +00002748 *
2749 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2750 * | 'PUBLIC' S PubidLiteral S SystemLiteral
Daniel Veillard1e346af1999-02-22 10:33:01 +00002751 *
2752 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2753 *
2754 * Returns the function returns SystemLiteral and in the second
2755 * case publicID receives PubidLiteral, is strict is off
2756 * it is possible to return NULL and have publicID set.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002757 */
2758
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002759xmlChar *
2760xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2761 xmlChar *URI = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002762
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002763 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002764 if ((CUR == 'S') && (NXT(1) == 'Y') &&
2765 (NXT(2) == 'S') && (NXT(3) == 'T') &&
2766 (NXT(4) == 'E') && (NXT(5) == 'M')) {
2767 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002768 if (!IS_BLANK(CUR)) {
2769 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002770 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002771 "Space required after 'SYSTEM'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002772 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002773 ctxt->wellFormed = 0;
2774 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002775 SKIP_BLANKS;
2776 URI = xmlParseSystemLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002777 if (URI == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002778 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002779 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002780 "xmlParseExternalID: SYSTEM, no URI\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002781 ctxt->errNo = XML_ERR_URI_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002782 ctxt->wellFormed = 0;
2783 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002784 } else if ((CUR == 'P') && (NXT(1) == 'U') &&
2785 (NXT(2) == 'B') && (NXT(3) == 'L') &&
2786 (NXT(4) == 'I') && (NXT(5) == 'C')) {
2787 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002788 if (!IS_BLANK(CUR)) {
2789 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002790 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002791 "Space required after 'PUBLIC'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002792 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002793 ctxt->wellFormed = 0;
2794 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002795 SKIP_BLANKS;
2796 *publicID = xmlParsePubidLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002797 if (*publicID == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002798 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002799 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800 "xmlParseExternalID: PUBLIC, no Public Identifier\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002801 ctxt->errNo = XML_ERR_PUBID_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002802 ctxt->wellFormed = 0;
2803 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002804 if (strict) {
2805 /*
2806 * We don't handle [83] so "S SystemLiteral" is required.
2807 */
2808 if (!IS_BLANK(CUR)) {
2809 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002810 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00002811 "Space required after the Public Identifier\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002812 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002813 ctxt->wellFormed = 0;
2814 }
2815 } else {
2816 /*
2817 * We handle [83] so we return immediately, if
2818 * "S SystemLiteral" is not detected. From a purely parsing
2819 * point of view that's a nice mess.
2820 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002821 const xmlChar *ptr = CUR_PTR;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002822 if (!IS_BLANK(*ptr)) return(NULL);
2823
2824 while (IS_BLANK(*ptr)) ptr++;
2825 if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002826 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002827 SKIP_BLANKS;
2828 URI = xmlParseSystemLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002829 if (URI == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002830 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002831 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002832 "xmlParseExternalID: PUBLIC, no URI\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002833 ctxt->errNo = XML_ERR_URI_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002834 ctxt->wellFormed = 0;
2835 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002836 }
2837 return(URI);
2838}
2839
Daniel Veillard11e00581998-10-24 18:27:49 +00002840/**
2841 * xmlParseComment:
Daniel Veillard1e346af1999-02-22 10:33:01 +00002842 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00002843 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002844 * Skip an XML (SGML) comment <!-- .... -->
Daniel Veillard260a68f1998-08-13 03:39:55 +00002845 * The spec says that "For compatibility, the string "--" (double-hyphen)
2846 * must not occur within comments. "
2847 *
2848 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
2849 */
Daniel Veillard517752b1999-04-05 12:20:10 +00002850void
Daniel Veillardb96e6431999-08-29 21:02:19 +00002851xmlParseComment(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002852 const xmlChar *q, *start;
2853 const xmlChar *r;
2854 xmlChar *val;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855
2856 /*
2857 * Check that there is a comment right here.
2858 */
2859 if ((CUR != '<') || (NXT(1) != '!') ||
Daniel Veillard517752b1999-04-05 12:20:10 +00002860 (NXT(2) != '-') || (NXT(3) != '-')) return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861
Daniel Veillardb05deb71999-08-10 19:04:08 +00002862 ctxt->instate = XML_PARSER_COMMENT;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002863 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 SKIP(4);
2865 start = q = CUR_PTR;
2866 NEXT;
2867 r = CUR_PTR;
2868 NEXT;
2869 while (IS_CHAR(CUR) &&
2870 ((CUR == ':') || (CUR != '>') ||
2871 (*r != '-') || (*q != '-'))) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002872 if ((*r == '-') && (*q == '-')) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002873 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002874 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002875 "Comment must not contain '--' (double-hyphen)`\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002876 ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002877 ctxt->wellFormed = 0;
2878 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002879 NEXT;r++;q++;
2880 }
2881 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002882 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002883 ctxt->sax->error(ctxt->userData,
2884 "Comment not terminated \n<!--%.50s\n", start);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002885 ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002886 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002887 } else {
2888 NEXT;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002889 val = xmlStrndup(start, q - start);
2890 if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
2891 ctxt->sax->comment(ctxt->userData, val);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002892 xmlFree(val);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002893 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002894}
2895
Daniel Veillard11e00581998-10-24 18:27:49 +00002896/**
2897 * xmlParsePITarget:
2898 * @ctxt: an XML parser context
2899 *
2900 * parse the name of a PI
Daniel Veillard260a68f1998-08-13 03:39:55 +00002901 *
2902 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
Daniel Veillard1e346af1999-02-22 10:33:01 +00002903 *
2904 * Returns the PITarget name or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002905 */
2906
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002907xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002908xmlParsePITarget(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002909 xmlChar *name;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002910
2911 name = xmlParseName(ctxt);
2912 if ((name != NULL) && (name[3] == 0) &&
2913 ((name[0] == 'x') || (name[0] == 'X')) &&
2914 ((name[1] == 'm') || (name[1] == 'M')) &&
2915 ((name[2] == 'l') || (name[2] == 'L'))) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002916 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
2917 ctxt->sax->error(ctxt->userData,
2918 "xmlParsePItarget: invalid name prefix 'xml'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002919 ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002920 /* ctxt->wellFormed = 0; !!! ? */
2921 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002922 return(NULL);
2923 }
2924 return(name);
2925}
2926
Daniel Veillard11e00581998-10-24 18:27:49 +00002927/**
2928 * xmlParsePI:
2929 * @ctxt: an XML parser context
2930 *
2931 * parse an XML Processing Instruction.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002932 *
2933 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
Daniel Veillard1e346af1999-02-22 10:33:01 +00002934 *
2935 * The processing is transfered to SAX once parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002936 */
2937
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002938void
2939xmlParsePI(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002940 xmlChar *target;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002941
2942 if ((CUR == '<') && (NXT(1) == '?')) {
2943 /*
2944 * this is a Processing Instruction.
2945 */
2946 SKIP(2);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002947 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002948
2949 /*
2950 * Parse the target name and check for special support like
2951 * namespace.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002952 */
2953 target = xmlParsePITarget(ctxt);
2954 if (target != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002955 const xmlChar *q;
Daniel Veillard517752b1999-04-05 12:20:10 +00002956
Daniel Veillardb96e6431999-08-29 21:02:19 +00002957 if (!IS_BLANK(CUR)) {
2958 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2959 ctxt->sax->error(ctxt->userData,
2960 "xmlParsePI: PI %s space expected\n", target);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002961 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002962 ctxt->wellFormed = 0;
2963 }
2964 SKIP_BLANKS;
2965 q = CUR_PTR;
Daniel Veillard517752b1999-04-05 12:20:10 +00002966 while (IS_CHAR(CUR) &&
2967 ((CUR != '?') || (NXT(1) != '>')))
2968 NEXT;
2969 if (!IS_CHAR(CUR)) {
2970 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002971 ctxt->sax->error(ctxt->userData,
Daniel Veillard517752b1999-04-05 12:20:10 +00002972 "xmlParsePI: PI %s never end ...\n", target);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002973 ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
Daniel Veillard517752b1999-04-05 12:20:10 +00002974 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002975 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002976 xmlChar *data;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002977
Daniel Veillard517752b1999-04-05 12:20:10 +00002978 data = xmlStrndup(q, CUR_PTR - q);
2979 SKIP(2);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002980
Daniel Veillard517752b1999-04-05 12:20:10 +00002981 /*
2982 * SAX: PI detected.
2983 */
2984 if ((ctxt->sax) &&
2985 (ctxt->sax->processingInstruction != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00002986 ctxt->sax->processingInstruction(ctxt->userData,
2987 target, data);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002988 xmlFree(data);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002989 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002990 xmlFree(target);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002991 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002992 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00002993 ctxt->sax->error(ctxt->userData,
2994 "xmlParsePI : no target name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002995 ctxt->errNo = XML_ERR_PI_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002996 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002997 }
2998 }
2999}
3000
Daniel Veillard11e00581998-10-24 18:27:49 +00003001/**
3002 * xmlParseNotationDecl:
3003 * @ctxt: an XML parser context
3004 *
3005 * parse a notation declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00003006 *
3007 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
3008 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003009 * Hence there is actually 3 choices:
3010 * 'PUBLIC' S PubidLiteral
3011 * 'PUBLIC' S PubidLiteral S SystemLiteral
3012 * and 'SYSTEM' S SystemLiteral
Daniel Veillard11e00581998-10-24 18:27:49 +00003013 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003014 * See the NOTE on xmlParseExternalID().
Daniel Veillard260a68f1998-08-13 03:39:55 +00003015 */
3016
Daniel Veillard0ba4d531998-11-01 19:34:31 +00003017void
3018xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003019 xmlChar *name;
3020 xmlChar *Pubid;
3021 xmlChar *Systemid;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003022
3023 if ((CUR == '<') && (NXT(1) == '!') &&
3024 (NXT(2) == 'N') && (NXT(3) == 'O') &&
3025 (NXT(4) == 'T') && (NXT(5) == 'A') &&
3026 (NXT(6) == 'T') && (NXT(7) == 'I') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003027 (NXT(8) == 'O') && (NXT(9) == 'N')) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003028 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003029 SKIP(10);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003030 if (!IS_BLANK(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003031 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003032 ctxt->sax->error(ctxt->userData,
3033 "Space required after '<!NOTATION'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003034 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003035 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 return;
3037 }
3038 SKIP_BLANKS;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003039
3040 name = xmlParseName(ctxt);
3041 if (name == NULL) {
3042 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003043 ctxt->sax->error(ctxt->userData,
3044 "NOTATION: Name expected here\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003045 ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003046 ctxt->wellFormed = 0;
3047 return;
3048 }
3049 if (!IS_BLANK(CUR)) {
3050 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003051 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003052 "Space required after the NOTATION name'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003053 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003054 ctxt->wellFormed = 0;
3055 return;
3056 }
3057 SKIP_BLANKS;
3058
Daniel Veillard260a68f1998-08-13 03:39:55 +00003059 /*
Daniel Veillard1e346af1999-02-22 10:33:01 +00003060 * Parse the IDs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003061 */
Daniel Veillard1e346af1999-02-22 10:33:01 +00003062 Systemid = xmlParseExternalID(ctxt, &Pubid, 1);
3063 SKIP_BLANKS;
3064
3065 if (CUR == '>') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003066 NEXT;
Daniel Veillard517752b1999-04-05 12:20:10 +00003067 if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003068 ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003069 } else {
3070 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003071 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003072 "'>' required to close NOTATION declaration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003073 ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003074 ctxt->wellFormed = 0;
3075 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00003076 xmlFree(name);
3077 if (Systemid != NULL) xmlFree(Systemid);
3078 if (Pubid != NULL) xmlFree(Pubid);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003079 }
3080}
3081
Daniel Veillard11e00581998-10-24 18:27:49 +00003082/**
3083 * xmlParseEntityDecl:
3084 * @ctxt: an XML parser context
3085 *
3086 * parse <!ENTITY declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00003087 *
3088 * [70] EntityDecl ::= GEDecl | PEDecl
3089 *
3090 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
3091 *
3092 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
3093 *
3094 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
3095 *
3096 * [74] PEDef ::= EntityValue | ExternalID
3097 *
3098 * [76] NDataDecl ::= S 'NDATA' S Name
Daniel Veillardb05deb71999-08-10 19:04:08 +00003099 *
3100 * [ VC: Notation Declared ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003101 * The Name must match the declared name of a notation.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003102 */
3103
Daniel Veillard0ba4d531998-11-01 19:34:31 +00003104void
3105xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003106 xmlChar *name = NULL;
3107 xmlChar *value = NULL;
3108 xmlChar *URI = NULL, *literal = NULL;
3109 xmlChar *ndata = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003110 int isParameter = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003111 xmlChar *orig = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003112
Daniel Veillardb05deb71999-08-10 19:04:08 +00003113 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003114 if ((CUR == '<') && (NXT(1) == '!') &&
3115 (NXT(2) == 'E') && (NXT(3) == 'N') &&
3116 (NXT(4) == 'T') && (NXT(5) == 'I') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003117 (NXT(6) == 'T') && (NXT(7) == 'Y')) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003118 ctxt->instate = XML_PARSER_ENTITY_DECL;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003119 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003120 SKIP(8);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003121 if (!IS_BLANK(CUR)) {
3122 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003123 ctxt->sax->error(ctxt->userData,
3124 "Space required after '<!ENTITY'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003125 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003126 ctxt->wellFormed = 0;
3127 }
3128 SKIP_BLANKS;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003129
3130 if (CUR == '%') {
3131 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003132 if (!IS_BLANK(CUR)) {
3133 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003134 ctxt->sax->error(ctxt->userData,
3135 "Space required after '%'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003136 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003137 ctxt->wellFormed = 0;
3138 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003139 SKIP_BLANKS;
3140 isParameter = 1;
3141 }
3142
3143 name = xmlParseName(ctxt);
3144 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003145 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003146 ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003147 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003148 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003149 return;
3150 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003151 if (!IS_BLANK(CUR)) {
3152 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003153 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003154 "Space required after the entity name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003155 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003156 ctxt->wellFormed = 0;
3157 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003158 SKIP_BLANKS;
3159
3160 /*
Daniel Veillard1e346af1999-02-22 10:33:01 +00003161 * handle the various case of definitions...
Daniel Veillard260a68f1998-08-13 03:39:55 +00003162 */
3163 if (isParameter) {
3164 if ((CUR == '"') || (CUR == '\''))
Daniel Veillard011b63c1999-06-02 17:44:04 +00003165 value = xmlParseEntityValue(ctxt, &orig);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003166 if (value) {
Daniel Veillard517752b1999-04-05 12:20:10 +00003167 if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003168 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003169 XML_INTERNAL_PARAMETER_ENTITY,
3170 NULL, NULL, value);
3171 }
3172 else {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003173 URI = xmlParseExternalID(ctxt, &literal, 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003174 if (URI) {
Daniel Veillard517752b1999-04-05 12:20:10 +00003175 if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003176 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003177 XML_EXTERNAL_PARAMETER_ENTITY,
3178 literal, URI, NULL);
3179 }
3180 }
3181 } else {
3182 if ((CUR == '"') || (CUR == '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003183 value = xmlParseEntityValue(ctxt, &orig);
Daniel Veillard517752b1999-04-05 12:20:10 +00003184 if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003185 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003186 XML_INTERNAL_GENERAL_ENTITY,
3187 NULL, NULL, value);
3188 } else {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003189 URI = xmlParseExternalID(ctxt, &literal, 1);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003190 if ((CUR != '>') && (!IS_BLANK(CUR))) {
3191 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003192 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003193 "Space required before 'NDATA'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003194 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003195 ctxt->wellFormed = 0;
3196 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003197 SKIP_BLANKS;
3198 if ((CUR == 'N') && (NXT(1) == 'D') &&
3199 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3200 (NXT(4) == 'A')) {
3201 SKIP(5);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003202 if (!IS_BLANK(CUR)) {
3203 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003204 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003205 "Space required after 'NDATA'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003206 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003207 ctxt->wellFormed = 0;
3208 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003209 SKIP_BLANKS;
3210 ndata = xmlParseName(ctxt);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003211 if ((ctxt->sax != NULL) &&
3212 (ctxt->sax->unparsedEntityDecl != NULL))
3213 ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003214 literal, URI, ndata);
3215 } else {
Daniel Veillard517752b1999-04-05 12:20:10 +00003216 if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003217 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003218 XML_EXTERNAL_GENERAL_PARSED_ENTITY,
3219 literal, URI, NULL);
3220 }
3221 }
3222 }
3223 SKIP_BLANKS;
3224 if (CUR != '>') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003225 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003226 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003227 "xmlParseEntityDecl: entity %s not terminated\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003228 ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003229 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003230 } else
3231 NEXT;
Daniel Veillard011b63c1999-06-02 17:44:04 +00003232 if (orig != NULL) {
3233 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00003234 * Ugly mechanism to save the raw entity value.
Daniel Veillard011b63c1999-06-02 17:44:04 +00003235 */
3236 xmlEntityPtr cur = NULL;
3237
Daniel Veillardb05deb71999-08-10 19:04:08 +00003238 if (isParameter) {
3239 if ((ctxt->sax != NULL) &&
3240 (ctxt->sax->getParameterEntity != NULL))
Daniel Veillardc08a2c61999-09-08 21:35:25 +00003241 cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003242 } else {
3243 if ((ctxt->sax != NULL) &&
3244 (ctxt->sax->getEntity != NULL))
Daniel Veillardc08a2c61999-09-08 21:35:25 +00003245 cur = ctxt->sax->getEntity(ctxt->userData, name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003246 }
3247 if (cur != NULL) {
3248 if (cur->orig != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003249 xmlFree(orig);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003250 else
3251 cur->orig = orig;
3252 } else
Daniel Veillard6454aec1999-09-02 22:04:43 +00003253 xmlFree(orig);
Daniel Veillard011b63c1999-06-02 17:44:04 +00003254 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00003255 if (name != NULL) xmlFree(name);
3256 if (value != NULL) xmlFree(value);
3257 if (URI != NULL) xmlFree(URI);
3258 if (literal != NULL) xmlFree(literal);
3259 if (ndata != NULL) xmlFree(ndata);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003260 }
3261}
3262
Daniel Veillard11e00581998-10-24 18:27:49 +00003263/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003264 * xmlParseDefaultDecl:
3265 * @ctxt: an XML parser context
3266 * @value: Receive a possible fixed default value for the attribute
3267 *
3268 * Parse an attribute default declaration
3269 *
3270 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
3271 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003272 * [ VC: Required Attribute ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003273 * if the default declaration is the keyword #REQUIRED, then the
3274 * attribute must be specified for all elements of the type in the
3275 * attribute-list declaration.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003276 *
3277 * [ VC: Attribute Default Legal ]
3278 * The declared default value must meet the lexical constraints of
3279 * the declared attribute type c.f. xmlValidateAttributeDecl()
3280 *
3281 * [ VC: Fixed Attribute Default ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003282 * if an attribute has a default value declared with the #FIXED
3283 * keyword, instances of that attribute must match the default value.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003284 *
3285 * [ WFC: No < in Attribute Values ]
3286 * handled in xmlParseAttValue()
3287 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003288 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
3289 * or XML_ATTRIBUTE_FIXED.
3290 */
3291
3292int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003293xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003294 int val;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003295 xmlChar *ret;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003296
3297 *value = NULL;
3298 if ((CUR == '#') && (NXT(1) == 'R') &&
3299 (NXT(2) == 'E') && (NXT(3) == 'Q') &&
3300 (NXT(4) == 'U') && (NXT(5) == 'I') &&
3301 (NXT(6) == 'R') && (NXT(7) == 'E') &&
3302 (NXT(8) == 'D')) {
3303 SKIP(9);
3304 return(XML_ATTRIBUTE_REQUIRED);
3305 }
3306 if ((CUR == '#') && (NXT(1) == 'I') &&
3307 (NXT(2) == 'M') && (NXT(3) == 'P') &&
3308 (NXT(4) == 'L') && (NXT(5) == 'I') &&
3309 (NXT(6) == 'E') && (NXT(7) == 'D')) {
3310 SKIP(8);
3311 return(XML_ATTRIBUTE_IMPLIED);
3312 }
3313 val = XML_ATTRIBUTE_NONE;
3314 if ((CUR == '#') && (NXT(1) == 'F') &&
3315 (NXT(2) == 'I') && (NXT(3) == 'X') &&
3316 (NXT(4) == 'E') && (NXT(5) == 'D')) {
3317 SKIP(6);
3318 val = XML_ATTRIBUTE_FIXED;
3319 if (!IS_BLANK(CUR)) {
3320 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003321 ctxt->sax->error(ctxt->userData,
3322 "Space required after '#FIXED'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003323 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003324 ctxt->wellFormed = 0;
3325 }
3326 SKIP_BLANKS;
3327 }
3328 ret = xmlParseAttValue(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003329 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003330 if (ret == NULL) {
3331 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003332 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003333 "Attribute default value declaration error\n");
3334 ctxt->wellFormed = 0;
3335 } else
3336 *value = ret;
3337 return(val);
3338}
3339
3340/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003341 * xmlParseNotationType:
3342 * @ctxt: an XML parser context
3343 *
3344 * parse an Notation attribute type.
3345 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003346 * Note: the leading 'NOTATION' S part has already being parsed...
3347 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003348 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3349 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003350 * [ VC: Notation Attributes ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003351 * Values of this type must match one of the notation names included
Daniel Veillardb05deb71999-08-10 19:04:08 +00003352 * in the declaration; all notation names in the declaration must be declared.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003353 *
3354 * Returns: the notation attribute tree built while parsing
3355 */
3356
3357xmlEnumerationPtr
3358xmlParseNotationType(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003359 xmlChar *name;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003360 xmlEnumerationPtr ret = NULL, last = NULL, cur;
3361
3362 if (CUR != '(') {
3363 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003364 ctxt->sax->error(ctxt->userData,
3365 "'(' required to start 'NOTATION'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003366 ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003367 ctxt->wellFormed = 0;
3368 return(NULL);
3369 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003370 SHRINK;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003371 do {
3372 NEXT;
3373 SKIP_BLANKS;
3374 name = xmlParseName(ctxt);
3375 if (name == NULL) {
3376 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003377 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003378 "Name expected in NOTATION declaration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003379 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003380 ctxt->wellFormed = 0;
3381 return(ret);
3382 }
3383 cur = xmlCreateEnumeration(name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003384 xmlFree(name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003385 if (cur == NULL) return(ret);
3386 if (last == NULL) ret = last = cur;
3387 else {
3388 last->next = cur;
3389 last = cur;
3390 }
3391 SKIP_BLANKS;
3392 } while (CUR == '|');
3393 if (CUR != ')') {
3394 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003395 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003396 "')' required to finish NOTATION declaration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003397 ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003398 ctxt->wellFormed = 0;
3399 return(ret);
3400 }
3401 NEXT;
3402 return(ret);
3403}
3404
3405/**
3406 * xmlParseEnumerationType:
3407 * @ctxt: an XML parser context
3408 *
3409 * parse an Enumeration attribute type.
3410 *
3411 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
3412 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003413 * [ VC: Enumeration ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003414 * Values of this type must match one of the Nmtoken tokens in
Daniel Veillardb05deb71999-08-10 19:04:08 +00003415 * the declaration
3416 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003417 * Returns: the enumeration attribute tree built while parsing
3418 */
3419
3420xmlEnumerationPtr
3421xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003422 xmlChar *name;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003423 xmlEnumerationPtr ret = NULL, last = NULL, cur;
3424
3425 if (CUR != '(') {
3426 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003427 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003428 "'(' required to start ATTLIST enumeration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003429 ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003430 ctxt->wellFormed = 0;
3431 return(NULL);
3432 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003433 SHRINK;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003434 do {
3435 NEXT;
3436 SKIP_BLANKS;
3437 name = xmlParseNmtoken(ctxt);
3438 if (name == NULL) {
3439 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003440 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003441 "NmToken expected in ATTLIST enumeration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003442 ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003443 ctxt->wellFormed = 0;
3444 return(ret);
3445 }
3446 cur = xmlCreateEnumeration(name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003447 xmlFree(name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003448 if (cur == NULL) return(ret);
3449 if (last == NULL) ret = last = cur;
3450 else {
3451 last->next = cur;
3452 last = cur;
3453 }
3454 SKIP_BLANKS;
3455 } while (CUR == '|');
3456 if (CUR != ')') {
3457 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003458 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003459 "')' required to finish ATTLIST enumeration\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003460 ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003461 ctxt->wellFormed = 0;
3462 return(ret);
3463 }
3464 NEXT;
3465 return(ret);
3466}
3467
3468/**
Daniel Veillard11e00581998-10-24 18:27:49 +00003469 * xmlParseEnumeratedType:
3470 * @ctxt: an XML parser context
Daniel Veillard1e346af1999-02-22 10:33:01 +00003471 * @tree: the enumeration tree built while parsing
Daniel Veillard11e00581998-10-24 18:27:49 +00003472 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003473 * parse an Enumerated attribute type.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003474 *
3475 * [57] EnumeratedType ::= NotationType | Enumeration
3476 *
3477 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3478 *
Daniel Veillard11e00581998-10-24 18:27:49 +00003479 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003480 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
Daniel Veillard260a68f1998-08-13 03:39:55 +00003481 */
3482
Daniel Veillard1e346af1999-02-22 10:33:01 +00003483int
3484xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3485 if ((CUR == 'N') && (NXT(1) == 'O') &&
3486 (NXT(2) == 'T') && (NXT(3) == 'A') &&
3487 (NXT(4) == 'T') && (NXT(5) == 'I') &&
3488 (NXT(6) == 'O') && (NXT(7) == 'N')) {
3489 SKIP(8);
3490 if (!IS_BLANK(CUR)) {
3491 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003492 ctxt->sax->error(ctxt->userData,
3493 "Space required after 'NOTATION'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003494 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003495 ctxt->wellFormed = 0;
3496 return(0);
3497 }
3498 SKIP_BLANKS;
3499 *tree = xmlParseNotationType(ctxt);
3500 if (*tree == NULL) return(0);
3501 return(XML_ATTRIBUTE_NOTATION);
3502 }
3503 *tree = xmlParseEnumerationType(ctxt);
3504 if (*tree == NULL) return(0);
3505 return(XML_ATTRIBUTE_ENUMERATION);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003506}
3507
Daniel Veillard11e00581998-10-24 18:27:49 +00003508/**
3509 * xmlParseAttributeType:
3510 * @ctxt: an XML parser context
Daniel Veillard1e346af1999-02-22 10:33:01 +00003511 * @tree: the enumeration tree built while parsing
Daniel Veillard11e00581998-10-24 18:27:49 +00003512 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003513 * parse the Attribute list def for an element
Daniel Veillard260a68f1998-08-13 03:39:55 +00003514 *
3515 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
3516 *
3517 * [55] StringType ::= 'CDATA'
3518 *
3519 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
3520 * 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
Daniel Veillard11e00581998-10-24 18:27:49 +00003521 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003522 * Validity constraints for attribute values syntax are checked in
3523 * xmlValidateAttributeValue()
3524 *
3525 * [ VC: ID ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003526 * Values of type ID must match the Name production. A name must not
Daniel Veillardb05deb71999-08-10 19:04:08 +00003527 * appear more than once in an XML document as a value of this type;
3528 * i.e., ID values must uniquely identify the elements which bear them.
3529 *
3530 * [ VC: One ID per Element Type ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003531 * No element type may have more than one ID attribute specified.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003532 *
3533 * [ VC: ID Attribute Default ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003534 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003535 *
3536 * [ VC: IDREF ]
3537 * Values of type IDREF must match the Name production, and values
Daniel Veillardb96e6431999-08-29 21:02:19 +00003538 * of type IDREFS must match Names; TODO each IDREF Name must match the value
3539 * of an ID attribute on some element in the XML document; i.e. IDREF
Daniel Veillardb05deb71999-08-10 19:04:08 +00003540 * values must match the value of some ID attribute.
3541 *
3542 * [ VC: Entity Name ]
3543 * Values of type ENTITY must match the Name production, values
Daniel Veillardb96e6431999-08-29 21:02:19 +00003544 * of type ENTITIES must match Names; TODO each Entity Name must match the
3545 * name of an unparsed entity declared in the DTD.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003546 *
3547 * [ VC: Name Token ]
3548 * Values of type NMTOKEN must match the Nmtoken production; values
3549 * of type NMTOKENS must match Nmtokens.
3550 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003551 * Returns the attribute type
Daniel Veillard260a68f1998-08-13 03:39:55 +00003552 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003553int
Daniel Veillard1e346af1999-02-22 10:33:01 +00003554xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003555 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003556 if ((CUR == 'C') && (NXT(1) == 'D') &&
3557 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3558 (NXT(4) == 'A')) {
3559 SKIP(5);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003560 return(XML_ATTRIBUTE_CDATA);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003561 } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3562 (NXT(2) == 'R') && (NXT(3) == 'E') &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00003563 (NXT(4) == 'F') && (NXT(5) == 'S')) {
3564 SKIP(6);
3565 return(XML_ATTRIBUTE_IDREFS);
3566 } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3567 (NXT(2) == 'R') && (NXT(3) == 'E') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003568 (NXT(4) == 'F')) {
3569 SKIP(5);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003570 return(XML_ATTRIBUTE_IDREF);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003571 } else if ((CUR == 'I') && (NXT(1) == 'D')) {
3572 SKIP(2);
3573 return(XML_ATTRIBUTE_ID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003574 } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3575 (NXT(2) == 'T') && (NXT(3) == 'I') &&
3576 (NXT(4) == 'T') && (NXT(5) == 'Y')) {
3577 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003578 return(XML_ATTRIBUTE_ENTITY);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003579 } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3580 (NXT(2) == 'T') && (NXT(3) == 'I') &&
3581 (NXT(4) == 'T') && (NXT(5) == 'I') &&
3582 (NXT(6) == 'E') && (NXT(7) == 'S')) {
3583 SKIP(8);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003584 return(XML_ATTRIBUTE_ENTITIES);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003585 } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3586 (NXT(2) == 'T') && (NXT(3) == 'O') &&
3587 (NXT(4) == 'K') && (NXT(5) == 'E') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003588 (NXT(6) == 'N') && (NXT(7) == 'S')) {
3589 SKIP(8);
3590 return(XML_ATTRIBUTE_NMTOKENS);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003591 } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3592 (NXT(2) == 'T') && (NXT(3) == 'O') &&
3593 (NXT(4) == 'K') && (NXT(5) == 'E') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003594 (NXT(6) == 'N')) {
3595 SKIP(7);
3596 return(XML_ATTRIBUTE_NMTOKEN);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003597 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003598 return(xmlParseEnumeratedType(ctxt, tree));
Daniel Veillard260a68f1998-08-13 03:39:55 +00003599}
3600
Daniel Veillard11e00581998-10-24 18:27:49 +00003601/**
3602 * xmlParseAttributeListDecl:
3603 * @ctxt: an XML parser context
3604 *
3605 * : parse the Attribute list def for an element
Daniel Veillard260a68f1998-08-13 03:39:55 +00003606 *
3607 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
3608 *
3609 * [53] AttDef ::= S Name S AttType S DefaultDecl
Daniel Veillard11e00581998-10-24 18:27:49 +00003610 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003611 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00003612void
3613xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003614 xmlChar *elemName;
3615 xmlChar *attrName;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003616 xmlEnumerationPtr tree;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003617
Daniel Veillard260a68f1998-08-13 03:39:55 +00003618 if ((CUR == '<') && (NXT(1) == '!') &&
3619 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3620 (NXT(4) == 'T') && (NXT(5) == 'L') &&
3621 (NXT(6) == 'I') && (NXT(7) == 'S') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003622 (NXT(8) == 'T')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003623 SKIP(9);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003624 if (!IS_BLANK(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003625 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003626 ctxt->sax->error(ctxt->userData,
3627 "Space required after '<!ATTLIST'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003628 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003629 ctxt->wellFormed = 0;
3630 }
3631 SKIP_BLANKS;
3632 elemName = xmlParseName(ctxt);
3633 if (elemName == NULL) {
3634 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003635 ctxt->sax->error(ctxt->userData,
3636 "ATTLIST: no name for Element\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003637 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003638 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003639 return;
3640 }
3641 SKIP_BLANKS;
3642 while (CUR != '>') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003643 const xmlChar *check = CUR_PTR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003644 int type;
3645 int def;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003646 xmlChar *defaultValue = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003647
Daniel Veillardb05deb71999-08-10 19:04:08 +00003648 tree = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003649 attrName = xmlParseName(ctxt);
3650 if (attrName == NULL) {
3651 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003652 ctxt->sax->error(ctxt->userData,
3653 "ATTLIST: no name for Attribute\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003654 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003655 ctxt->wellFormed = 0;
3656 break;
3657 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003658 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003659 if (!IS_BLANK(CUR)) {
3660 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003661 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003662 "Space required after the attribute name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003663 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003664 ctxt->wellFormed = 0;
3665 break;
3666 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003667 SKIP_BLANKS;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003668
Daniel Veillard1e346af1999-02-22 10:33:01 +00003669 type = xmlParseAttributeType(ctxt, &tree);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003670 if (type <= 0) break;
3671
Daniel Veillardb05deb71999-08-10 19:04:08 +00003672 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003673 if (!IS_BLANK(CUR)) {
3674 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003675 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003676 "Space required after the attribute type\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003677 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003678 ctxt->wellFormed = 0;
3679 break;
3680 }
3681 SKIP_BLANKS;
3682
3683 def = xmlParseDefaultDecl(ctxt, &defaultValue);
3684 if (def <= 0) break;
3685
Daniel Veillardb05deb71999-08-10 19:04:08 +00003686 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003687 if (CUR != '>') {
3688 if (!IS_BLANK(CUR)) {
3689 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003690 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003691 "Space required after the attribute default value\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003692 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003693 ctxt->wellFormed = 0;
3694 break;
3695 }
3696 SKIP_BLANKS;
3697 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003698 if (check == CUR_PTR) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003699 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003700 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003701 "xmlParseAttributeListDecl: detected internal error\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003702 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003703 break;
3704 }
Daniel Veillard517752b1999-04-05 12:20:10 +00003705 if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003706 ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003707 type, def, defaultValue, tree);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003708 if (attrName != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003709 xmlFree(attrName);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003710 if (defaultValue != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003711 xmlFree(defaultValue);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003712 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003713 }
3714 if (CUR == '>')
3715 NEXT;
3716
Daniel Veillard6454aec1999-09-02 22:04:43 +00003717 xmlFree(elemName);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003718 }
3719}
3720
Daniel Veillard11e00581998-10-24 18:27:49 +00003721/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003722 * xmlParseElementMixedContentDecl:
Daniel Veillard11e00581998-10-24 18:27:49 +00003723 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00003724 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003725 * parse the declaration for a Mixed Element content
3726 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
Daniel Veillard260a68f1998-08-13 03:39:55 +00003727 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003728 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
3729 * '(' S? '#PCDATA' S? ')'
3730 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003731 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
3732 *
3733 * [ VC: No Duplicate Types ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003734 * The same name must not appear more than once in a single
3735 * mixed-content declaration.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003736 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003737 * returns: the list of the xmlElementContentPtr describing the element choices
3738 */
3739xmlElementContentPtr
3740xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillard1899e851999-02-01 12:18:54 +00003741 xmlElementContentPtr ret = NULL, cur = NULL, n;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003742 xmlChar *elem = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003743
Daniel Veillardb05deb71999-08-10 19:04:08 +00003744 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003745 if ((CUR == '#') && (NXT(1) == 'P') &&
3746 (NXT(2) == 'C') && (NXT(3) == 'D') &&
3747 (NXT(4) == 'A') && (NXT(5) == 'T') &&
3748 (NXT(6) == 'A')) {
3749 SKIP(7);
3750 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003751 SHRINK;
Daniel Veillard3b9def11999-01-31 22:15:06 +00003752 if (CUR == ')') {
3753 NEXT;
3754 ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3755 return(ret);
3756 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003757 if ((CUR == '(') || (CUR == '|')) {
3758 ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3759 if (ret == NULL) return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003760 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003761 while (CUR == '|') {
Daniel Veillard1899e851999-02-01 12:18:54 +00003762 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003763 if (elem == NULL) {
3764 ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3765 if (ret == NULL) return(NULL);
3766 ret->c1 = cur;
Daniel Veillard1899e851999-02-01 12:18:54 +00003767 cur = ret;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003768 } else {
Daniel Veillard1899e851999-02-01 12:18:54 +00003769 n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3770 if (n == NULL) return(NULL);
3771 n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3772 cur->c2 = n;
3773 cur = n;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003774 xmlFree(elem);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003775 }
3776 SKIP_BLANKS;
3777 elem = xmlParseName(ctxt);
3778 if (elem == NULL) {
3779 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003780 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003781 "xmlParseElementMixedContentDecl : Name expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003782 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003783 ctxt->wellFormed = 0;
3784 xmlFreeElementContent(cur);
3785 return(NULL);
3786 }
3787 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003788 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003789 }
Daniel Veillard3b9def11999-01-31 22:15:06 +00003790 if ((CUR == ')') && (NXT(1) == '*')) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003791 if (elem != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003792 cur->c2 = xmlNewElementContent(elem,
3793 XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003794 xmlFree(elem);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003795 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003796 ret->ocur = XML_ELEMENT_CONTENT_MULT;
3797 SKIP(2);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003798 } else {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003799 if (elem != NULL) xmlFree(elem);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003800 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003801 ctxt->sax->error(ctxt->userData,
Daniel Veillard3b9def11999-01-31 22:15:06 +00003802 "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003803 ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003804 ctxt->wellFormed = 0;
3805 xmlFreeElementContent(ret);
3806 return(NULL);
3807 }
3808
3809 } else {
3810 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003811 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003812 "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003813 ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003814 ctxt->wellFormed = 0;
3815 }
3816 return(ret);
3817}
3818
3819/**
3820 * xmlParseElementChildrenContentDecl:
3821 * @ctxt: an XML parser context
3822 *
3823 * parse the declaration for a Mixed Element content
3824 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
3825 *
3826 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003827 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
3828 *
3829 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
3830 *
3831 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
3832 *
3833 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
3834 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003835 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
3836 * TODO Parameter-entity replacement text must be properly nested
3837 * with parenthetized groups. That is to say, if either of the
3838 * opening or closing parentheses in a choice, seq, or Mixed
3839 * construct is contained in the replacement text for a parameter
3840 * entity, both must be contained in the same replacement text. For
3841 * interoperability, if a parameter-entity reference appears in a
3842 * choice, seq, or Mixed construct, its replacement text should not
3843 * be empty, and neither the first nor last non-blank character of
3844 * the replacement text should be a connector (| or ,).
3845 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003846 * returns: the tree of xmlElementContentPtr describing the element
3847 * hierarchy.
3848 */
3849xmlElementContentPtr
3850xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
3851 xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003852 xmlChar *elem;
3853 xmlChar type = 0;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003854
3855 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003856 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003857 if (CUR == '(') {
3858 /* Recurse on first child */
3859 NEXT;
3860 SKIP_BLANKS;
3861 cur = ret = xmlParseElementChildrenContentDecl(ctxt);
3862 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003863 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003864 } else {
3865 elem = xmlParseName(ctxt);
3866 if (elem == NULL) {
3867 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003868 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003869 "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003870 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003871 ctxt->wellFormed = 0;
3872 return(NULL);
3873 }
3874 cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003875 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003876 if (CUR == '?') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003877 cur->ocur = XML_ELEMENT_CONTENT_OPT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003878 NEXT;
3879 } else if (CUR == '*') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003880 cur->ocur = XML_ELEMENT_CONTENT_MULT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003881 NEXT;
3882 } else if (CUR == '+') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003883 cur->ocur = XML_ELEMENT_CONTENT_PLUS;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003884 NEXT;
3885 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003886 cur->ocur = XML_ELEMENT_CONTENT_ONCE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003887 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00003888 xmlFree(elem);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003889 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003890 }
3891 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003892 SHRINK;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003893 while (CUR != ')') {
3894 /*
3895 * Each loop we parse one separator and one element.
3896 */
3897 if (CUR == ',') {
3898 if (type == 0) type = CUR;
3899
3900 /*
3901 * Detect "Name | Name , Name" error
3902 */
3903 else if (type != CUR) {
3904 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003905 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003906 "xmlParseElementChildrenContentDecl : '%c' expected\n",
3907 type);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003908 ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003909 ctxt->wellFormed = 0;
3910 xmlFreeElementContent(ret);
3911 return(NULL);
3912 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003913 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003914
3915 op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
3916 if (op == NULL) {
3917 xmlFreeElementContent(ret);
3918 return(NULL);
3919 }
3920 if (last == NULL) {
3921 op->c1 = ret;
3922 ret = cur = op;
3923 } else {
3924 cur->c2 = op;
3925 op->c1 = last;
3926 cur =op;
Daniel Veillard1899e851999-02-01 12:18:54 +00003927 last = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003928 }
3929 } else if (CUR == '|') {
3930 if (type == 0) type = CUR;
3931
3932 /*
3933 * Detect "Name , Name | Name" error
3934 */
3935 else if (type != CUR) {
3936 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003937 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003938 "xmlParseElementChildrenContentDecl : '%c' expected\n",
3939 type);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003940 ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003941 ctxt->wellFormed = 0;
3942 xmlFreeElementContent(ret);
3943 return(NULL);
3944 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003945 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003946
3947 op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3948 if (op == NULL) {
3949 xmlFreeElementContent(ret);
3950 return(NULL);
3951 }
3952 if (last == NULL) {
3953 op->c1 = ret;
3954 ret = cur = op;
3955 } else {
3956 cur->c2 = op;
3957 op->c1 = last;
3958 cur =op;
Daniel Veillard1899e851999-02-01 12:18:54 +00003959 last = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003960 }
3961 } else {
3962 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003963 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003964 "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
3965 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003966 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003967 xmlFreeElementContent(ret);
3968 return(NULL);
3969 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003970 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003971 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003972 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003973 if (CUR == '(') {
3974 /* Recurse on second child */
3975 NEXT;
3976 SKIP_BLANKS;
Daniel Veillard1899e851999-02-01 12:18:54 +00003977 last = xmlParseElementChildrenContentDecl(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003978 SKIP_BLANKS;
3979 } else {
3980 elem = xmlParseName(ctxt);
3981 if (elem == NULL) {
3982 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003983 ctxt->sax->error(ctxt->userData,
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003984 "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003985 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003986 ctxt->wellFormed = 0;
3987 return(NULL);
3988 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003989 last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003990 xmlFree(elem);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003991 if (CUR == '?') {
3992 last->ocur = XML_ELEMENT_CONTENT_OPT;
3993 NEXT;
3994 } else if (CUR == '*') {
3995 last->ocur = XML_ELEMENT_CONTENT_MULT;
3996 NEXT;
3997 } else if (CUR == '+') {
3998 last->ocur = XML_ELEMENT_CONTENT_PLUS;
3999 NEXT;
4000 } else {
4001 last->ocur = XML_ELEMENT_CONTENT_ONCE;
4002 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004003 }
4004 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004005 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004006 }
Daniel Veillard1899e851999-02-01 12:18:54 +00004007 if ((cur != NULL) && (last != NULL)) {
4008 cur->c2 = last;
4009 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004010 NEXT;
4011 if (CUR == '?') {
4012 ret->ocur = XML_ELEMENT_CONTENT_OPT;
4013 NEXT;
4014 } else if (CUR == '*') {
4015 ret->ocur = XML_ELEMENT_CONTENT_MULT;
4016 NEXT;
4017 } else if (CUR == '+') {
4018 ret->ocur = XML_ELEMENT_CONTENT_PLUS;
4019 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004020 }
4021 return(ret);
4022}
4023
4024/**
4025 * xmlParseElementContentDecl:
4026 * @ctxt: an XML parser context
4027 * @name: the name of the element being defined.
4028 * @result: the Element Content pointer will be stored here if any
Daniel Veillard260a68f1998-08-13 03:39:55 +00004029 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004030 * parse the declaration for an Element content either Mixed or Children,
4031 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
4032 *
4033 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
Daniel Veillard11e00581998-10-24 18:27:49 +00004034 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004035 * returns: the type of element content XML_ELEMENT_TYPE_xxx
Daniel Veillard260a68f1998-08-13 03:39:55 +00004036 */
4037
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004038int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004039xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004040 xmlElementContentPtr *result) {
4041
4042 xmlElementContentPtr tree = NULL;
4043 int res;
4044
4045 *result = NULL;
4046
4047 if (CUR != '(') {
4048 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004049 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004050 "xmlParseElementContentDecl : '(' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004051 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004052 ctxt->wellFormed = 0;
4053 return(-1);
4054 }
4055 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004056 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004057 SKIP_BLANKS;
4058 if ((CUR == '#') && (NXT(1) == 'P') &&
4059 (NXT(2) == 'C') && (NXT(3) == 'D') &&
4060 (NXT(4) == 'A') && (NXT(5) == 'T') &&
4061 (NXT(6) == 'A')) {
4062 tree = xmlParseElementMixedContentDecl(ctxt);
4063 res = XML_ELEMENT_TYPE_MIXED;
4064 } else {
4065 tree = xmlParseElementChildrenContentDecl(ctxt);
4066 res = XML_ELEMENT_TYPE_ELEMENT;
4067 }
4068 SKIP_BLANKS;
4069 /****************************
4070 if (CUR != ')') {
4071 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004072 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004073 "xmlParseElementContentDecl : ')' expected\n");
4074 ctxt->wellFormed = 0;
4075 return(-1);
4076 }
4077 ****************************/
Daniel Veillard3b9def11999-01-31 22:15:06 +00004078 *result = tree;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004079 return(res);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004080}
4081
Daniel Veillard11e00581998-10-24 18:27:49 +00004082/**
4083 * xmlParseElementDecl:
4084 * @ctxt: an XML parser context
4085 *
4086 * parse an Element declaration.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004087 *
4088 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
4089 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004090 * [ VC: Unique Element Type Declaration ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00004091 * No element type may be declared more than once
Daniel Veillard1e346af1999-02-22 10:33:01 +00004092 *
4093 * Returns the type of the element, or -1 in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +00004094 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004095int
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004096xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004097 xmlChar *name;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004098 int ret = -1;
4099 xmlElementContentPtr content = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004100
Daniel Veillardb05deb71999-08-10 19:04:08 +00004101 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004102 if ((CUR == '<') && (NXT(1) == '!') &&
4103 (NXT(2) == 'E') && (NXT(3) == 'L') &&
4104 (NXT(4) == 'E') && (NXT(5) == 'M') &&
4105 (NXT(6) == 'E') && (NXT(7) == 'N') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004106 (NXT(8) == 'T')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004107 SKIP(9);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004108 if (!IS_BLANK(CUR)) {
4109 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004110 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004111 "Space required after 'ELEMENT'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004112 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004113 ctxt->wellFormed = 0;
4114 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004115 SKIP_BLANKS;
4116 name = xmlParseName(ctxt);
4117 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004118 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004119 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004120 "xmlParseElementDecl: no name for Element\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004121 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004122 ctxt->wellFormed = 0;
4123 return(-1);
4124 }
4125 if (!IS_BLANK(CUR)) {
4126 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004127 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004128 "Space required after the element name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004129 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004130 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004131 }
4132 SKIP_BLANKS;
4133 if ((CUR == 'E') && (NXT(1) == 'M') &&
4134 (NXT(2) == 'P') && (NXT(3) == 'T') &&
4135 (NXT(4) == 'Y')) {
4136 SKIP(5);
4137 /*
4138 * Element must always be empty.
4139 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004140 ret = XML_ELEMENT_TYPE_EMPTY;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004141 } else if ((CUR == 'A') && (NXT(1) == 'N') &&
4142 (NXT(2) == 'Y')) {
4143 SKIP(3);
4144 /*
4145 * Element is a generic container.
4146 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004147 ret = XML_ELEMENT_TYPE_ANY;
4148 } else if (CUR == '(') {
4149 ret = xmlParseElementContentDecl(ctxt, name, &content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004150 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004151 /*
4152 * [ WFC: PEs in Internal Subset ] error handling.
4153 */
4154 if ((CUR == '%') && (ctxt->external == 0) &&
4155 (ctxt->inputNr == 1)) {
4156 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4157 ctxt->sax->error(ctxt->userData,
4158 "PEReference: forbidden within markup decl in internal subset\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004159 ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004160 } else {
4161 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4162 ctxt->sax->error(ctxt->userData,
4163 "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004164 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004165 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004166 ctxt->wellFormed = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +00004167 if (name != NULL) xmlFree(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004168 return(-1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004169 }
4170 SKIP_BLANKS;
4171 if (CUR != '>') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004172 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004173 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00004174 "xmlParseElementDecl: expected '>' at the end\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004175 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004176 ctxt->wellFormed = 0;
4177 } else {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004178 NEXT;
Daniel Veillard517752b1999-04-05 12:20:10 +00004179 if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00004180 ctxt->sax->elementDecl(ctxt->userData, name, ret,
4181 content);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004182 }
Daniel Veillard14fff061999-06-22 21:49:07 +00004183 if (content != NULL) {
4184 xmlFreeElementContent(content);
4185 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004186 if (name != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00004187 xmlFree(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004188 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004189 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004190 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004191}
4192
Daniel Veillard11e00581998-10-24 18:27:49 +00004193/**
4194 * xmlParseMarkupDecl:
4195 * @ctxt: an XML parser context
4196 *
4197 * parse Markup declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00004198 *
4199 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
4200 * NotationDecl | PI | Comment
4201 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004202 * [ VC: Proper Declaration/PE Nesting ]
4203 * TODO Parameter-entity replacement text must be properly nested with
4204 * markup declarations. That is to say, if either the first character
4205 * or the last character of a markup declaration (markupdecl above) is
4206 * contained in the replacement text for a parameter-entity reference,
4207 * both must be contained in the same replacement text.
4208 *
4209 * [ WFC: PEs in Internal Subset ]
4210 * In the internal DTD subset, parameter-entity references can occur
4211 * only where markup declarations can occur, not within markup declarations.
4212 * (This does not apply to references that occur in external parameter
4213 * entities or to the external subset.)
Daniel Veillard260a68f1998-08-13 03:39:55 +00004214 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004215void
4216xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004217 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004218 xmlParseElementDecl(ctxt);
4219 xmlParseAttributeListDecl(ctxt);
4220 xmlParseEntityDecl(ctxt);
4221 xmlParseNotationDecl(ctxt);
4222 xmlParsePI(ctxt);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004223 xmlParseComment(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004224 /*
4225 * This is only for internal subset. On external entities,
4226 * the replacement is done before parsing stage
4227 */
4228 if ((ctxt->external == 0) && (ctxt->inputNr == 1))
4229 xmlParsePEReference(ctxt);
4230 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004231}
4232
Daniel Veillard11e00581998-10-24 18:27:49 +00004233/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004234 * xmlParseTextDecl:
4235 * @ctxt: an XML parser context
4236 *
4237 * parse an XML declaration header for external entities
4238 *
4239 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
4240 *
4241 * Returns the only valuable info for an external parsed entity, the encoding
4242 */
4243
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004244xmlChar *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004245xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004246 xmlChar *version;
4247 xmlChar *encoding = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004248
4249 /*
4250 * We know that '<?xml' is here.
4251 */
4252 SKIP(5);
4253
4254 if (!IS_BLANK(CUR)) {
4255 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004256 ctxt->sax->error(ctxt->userData,
4257 "Space needed after '<?xml'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004258 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004259 ctxt->wellFormed = 0;
4260 }
4261 SKIP_BLANKS;
4262
4263 /*
4264 * We may have the VersionInfo here.
4265 */
4266 version = xmlParseVersionInfo(ctxt);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004267 if (version == NULL)
4268 version = xmlCharStrdup(XML_DEFAULT_VERSION);
4269 ctxt->version = xmlStrdup(version);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004270 xmlFree(version);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004271
4272 /*
4273 * We must have the encoding declaration
4274 */
4275 if (!IS_BLANK(CUR)) {
4276 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004277 ctxt->sax->error(ctxt->userData, "Space needed here\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004278 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004279 ctxt->wellFormed = 0;
4280 }
4281 encoding = xmlParseEncodingDecl(ctxt);
4282
4283 SKIP_BLANKS;
4284 if ((CUR == '?') && (NXT(1) == '>')) {
4285 SKIP(2);
4286 } else if (CUR == '>') {
4287 /* Deprecated old WD ... */
4288 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004289 ctxt->sax->error(ctxt->userData,
4290 "XML declaration must end-up with '?>'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004291 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004292 ctxt->wellFormed = 0;
4293 NEXT;
4294 } else {
4295 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004296 ctxt->sax->error(ctxt->userData,
4297 "parsing XML declaration: '?>' expected\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004298 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004299 ctxt->wellFormed = 0;
4300 MOVETO_ENDTAG(CUR_PTR);
4301 NEXT;
4302 }
4303 return(encoding);
4304}
4305
4306/*
4307 * xmlParseConditionalSections
4308 * @ctxt: an XML parser context
4309 *
4310 * TODO : Conditionnal section are not yet supported !
4311 *
4312 * [61] conditionalSect ::= includeSect | ignoreSect
4313 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
4314 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
4315 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
4316 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
4317 */
4318
4319void
4320xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
4321 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4322 ctxt->sax->warning(ctxt->userData,
4323 "XML conditional section not supported\n");
4324 /*
4325 * Skip up to the end of the conditionnal section.
4326 */
4327 while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>')))
4328 NEXT;
4329 if (CUR == 0) {
4330 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4331 ctxt->sax->error(ctxt->userData,
4332 "XML conditional section not closed\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004333 ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004334 ctxt->wellFormed = 0;
4335 }
4336}
4337
4338/**
Daniel Veillard00fdf371999-10-08 09:40:39 +00004339 * xmlParseExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004340 * @ctxt: an XML parser context
Daniel Veillard00fdf371999-10-08 09:40:39 +00004341 * @ExternalID: the external identifier
4342 * @SystemID: the system identifier (or URL)
Daniel Veillard011b63c1999-06-02 17:44:04 +00004343 *
4344 * parse Markup declarations from an external subset
4345 *
4346 * [30] extSubset ::= textDecl? extSubsetDecl
4347 *
4348 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004349 */
4350void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004351xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
4352 const xmlChar *SystemID) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004353 if ((CUR == '<') && (NXT(1) == '?') &&
4354 (NXT(2) == 'x') && (NXT(3) == 'm') &&
4355 (NXT(4) == 'l')) {
4356 xmlParseTextDecl(ctxt);
4357 }
4358 if (ctxt->myDoc == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004359 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004360 }
4361 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
4362 xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
4363
Daniel Veillardb05deb71999-08-10 19:04:08 +00004364 ctxt->instate = XML_PARSER_DTD;
4365 ctxt->external = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004366 while (((CUR == '<') && (NXT(1) == '?')) ||
4367 ((CUR == '<') && (NXT(1) == '!')) ||
4368 IS_BLANK(CUR)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004369 const xmlChar *check = CUR_PTR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004370 int cons = ctxt->input->consumed;
4371
Daniel Veillard011b63c1999-06-02 17:44:04 +00004372 if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4373 xmlParseConditionalSections(ctxt);
4374 } else if (IS_BLANK(CUR)) {
4375 NEXT;
4376 } else if (CUR == '%') {
4377 xmlParsePEReference(ctxt);
4378 } else
4379 xmlParseMarkupDecl(ctxt);
4380
4381 /*
4382 * Pop-up of finished entities.
4383 */
4384 while ((CUR == 0) && (ctxt->inputNr > 1))
4385 xmlPopInput(ctxt);
4386
Daniel Veillardb96e6431999-08-29 21:02:19 +00004387 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
4388 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4389 ctxt->sax->error(ctxt->userData,
4390 "Content error in the external subset\n");
4391 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004392 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004393 break;
4394 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004395 }
4396
4397 if (CUR != 0) {
4398 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4399 ctxt->sax->error(ctxt->userData,
4400 "Extra content at the end of the document\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004401 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004402 ctxt->wellFormed = 0;
4403 }
4404
4405}
4406
4407/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004408 * xmlParseReference:
4409 * @ctxt: an XML parser context
4410 *
4411 * parse and handle entity references in content, depending on the SAX
4412 * interface, this may end-up in a call to character() if this is a
4413 * CharRef, a predefined entity, if there is no reference() callback.
4414 * or if the parser was asked to switch to that mode.
4415 *
4416 * [67] Reference ::= EntityRef | CharRef
4417 */
4418void
4419xmlParseReference(xmlParserCtxtPtr ctxt) {
4420 xmlEntityPtr ent;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004421 xmlChar *val;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004422 if (CUR != '&') return;
4423
Daniel Veillardb96e6431999-08-29 21:02:19 +00004424 if (ctxt->inputNr > 1) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004425 xmlChar cur[2] = { '&' , 0 } ;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004426
4427 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4428 ctxt->sax->characters(ctxt->userData, cur, 1);
4429 if (ctxt->token == '&')
4430 ctxt->token = 0;
4431 else {
4432 SKIP(1);
4433 }
4434 return;
4435 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004436 if (NXT(1) == '#') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004437 xmlChar out[2];
Daniel Veillard011b63c1999-06-02 17:44:04 +00004438 int val = xmlParseCharRef(ctxt);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004439 /* invalid for UTF-8 variable encoding !!!!! */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004440 out[0] = val;
4441 out[1] = 0;
4442 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4443 ctxt->sax->characters(ctxt->userData, out, 1);
4444 } else {
4445 ent = xmlParseEntityRef(ctxt);
4446 if (ent == NULL) return;
4447 if ((ent->name != NULL) &&
Daniel Veillardb96e6431999-08-29 21:02:19 +00004448 (ent->type != XML_INTERNAL_PREDEFINED_ENTITY)) {
4449 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
4450 (ctxt->replaceEntities == 0)) {
4451 /*
4452 * Create a node.
4453 */
4454 ctxt->sax->reference(ctxt->userData, ent->name);
4455 return;
4456 } else if (ctxt->replaceEntities) {
4457 xmlParserInputPtr input;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004458
Daniel Veillardb96e6431999-08-29 21:02:19 +00004459 input = xmlNewEntityInputStream(ctxt, ent);
4460 xmlPushInput(ctxt, input);
4461 return;
4462 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004463 }
4464 val = ent->content;
4465 if (val == NULL) return;
4466 /*
4467 * inline the entity.
4468 */
4469 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4470 ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
4471 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004472}
4473
Daniel Veillard11e00581998-10-24 18:27:49 +00004474/**
4475 * xmlParseEntityRef:
4476 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00004477 *
4478 * parse ENTITY references declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00004479 *
4480 * [68] EntityRef ::= '&' Name ';'
Daniel Veillard1e346af1999-02-22 10:33:01 +00004481 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004482 * [ WFC: Entity Declared ]
4483 * In a document without any DTD, a document with only an internal DTD
4484 * subset which contains no parameter entity references, or a document
4485 * with "standalone='yes'", the Name given in the entity reference
4486 * must match that in an entity declaration, except that well-formed
4487 * documents need not declare any of the following entities: amp, lt,
4488 * gt, apos, quot. The declaration of a parameter entity must precede
4489 * any reference to it. Similarly, the declaration of a general entity
4490 * must precede any reference to it which appears in a default value in an
4491 * attribute-list declaration. Note that if entities are declared in the
4492 * external subset or in external parameter entities, a non-validating
4493 * processor is not obligated to read and process their declarations;
4494 * for such documents, the rule that an entity must be declared is a
4495 * well-formedness constraint only if standalone='yes'.
4496 *
4497 * [ WFC: Parsed Entity ]
4498 * An entity reference must not contain the name of an unparsed entity
4499 *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004500 * Returns the xmlEntityPtr if found, or NULL otherwise.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004501 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004502xmlEntityPtr
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004503xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004504 xmlChar *name;
Daniel Veillard517752b1999-04-05 12:20:10 +00004505 xmlEntityPtr ent = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004506
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004507 GROW;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004508
Daniel Veillard260a68f1998-08-13 03:39:55 +00004509 if (CUR == '&') {
4510 NEXT;
4511 name = xmlParseName(ctxt);
4512 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004513 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00004514 ctxt->sax->error(ctxt->userData,
4515 "xmlParseEntityRef: no name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004516 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004517 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004518 } else {
4519 if (CUR == ';') {
4520 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004521 /*
Daniel Veillard011b63c1999-06-02 17:44:04 +00004522 * Ask first SAX for entity resolution, otherwise try the
4523 * predefined set.
4524 */
4525 if (ctxt->sax != NULL) {
4526 if (ctxt->sax->getEntity != NULL)
4527 ent = ctxt->sax->getEntity(ctxt->userData, name);
4528 if (ent == NULL)
4529 ent = xmlGetPredefinedEntity(name);
4530 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004531 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00004532 * [ WFC: Entity Declared ]
4533 * In a document without any DTD, a document with only an
4534 * internal DTD subset which contains no parameter entity
4535 * references, or a document with "standalone='yes'", the
4536 * Name given in the entity reference must match that in an
4537 * entity declaration, except that well-formed documents
4538 * need not declare any of the following entities: amp, lt,
4539 * gt, apos, quot.
4540 * The declaration of a parameter entity must precede any
4541 * reference to it.
4542 * Similarly, the declaration of a general entity must
4543 * precede any reference to it which appears in a default
4544 * value in an attribute-list declaration. Note that if
4545 * entities are declared in the external subset or in
4546 * external parameter entities, a non-validating processor
4547 * is not obligated to read and process their declarations;
4548 * for such documents, the rule that an entity must be
4549 * declared is a well-formedness constraint only if
4550 * standalone='yes'.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004551 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004552 if (ent == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004553 if ((ctxt->standalone == 1) ||
4554 ((ctxt->hasExternalSubset == 0) &&
4555 (ctxt->hasPErefs == 0))) {
4556 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00004557 ctxt->sax->error(ctxt->userData,
4558 "Entity '%s' not defined\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004559 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004560 ctxt->wellFormed = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004561 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004562 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4563 ctxt->sax->warning(ctxt->userData,
4564 "Entity '%s' not defined\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004565 ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004566 }
4567 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004568
4569 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00004570 * [ WFC: Parsed Entity ]
4571 * An entity reference must not contain the name of an
4572 * unparsed entity
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004573 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00004574 else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4575 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4576 ctxt->sax->error(ctxt->userData,
4577 "Entity reference to unparsed entity %s\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004578 ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004579 ctxt->wellFormed = 0;
4580 }
4581
4582 /*
4583 * [ WFC: No External Entity References ]
4584 * Attribute values cannot contain direct or indirect
4585 * entity references to external entities.
4586 */
4587 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4588 (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4589 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4590 ctxt->sax->error(ctxt->userData,
4591 "Attribute references external entity '%s'\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004592 ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004593 ctxt->wellFormed = 0;
4594 }
4595 /*
4596 * [ WFC: No < in Attribute Values ]
4597 * The replacement text of any entity referred to directly or
4598 * indirectly in an attribute value (other than "&lt;") must
4599 * not contain a <.
4600 */
4601 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
Daniel Veillardb96e6431999-08-29 21:02:19 +00004602 (ent != NULL) &&
4603 (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00004604 (ent->content != NULL) &&
4605 (xmlStrchr(ent->content, '<'))) {
4606 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4607 ctxt->sax->error(ctxt->userData,
4608 "'<' in entity '%s' is not allowed in attributes values\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004609 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004610 ctxt->wellFormed = 0;
4611 }
4612
4613 /*
4614 * Internal check, no parameter entities here ...
4615 */
4616 else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004617 switch (ent->type) {
4618 case XML_INTERNAL_PARAMETER_ENTITY:
4619 case XML_EXTERNAL_PARAMETER_ENTITY:
4620 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004621 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004622 "Attempt to reference the parameter entity '%s'\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004623 ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004624 ctxt->wellFormed = 0;
4625 break;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004626 }
4627 }
4628
4629 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00004630 * [ WFC: No Recursion ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00004631 * TODO A parsed entity must not contain a recursive reference
4632 * to itself, either directly or indirectly.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004633 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00004634
Daniel Veillard011b63c1999-06-02 17:44:04 +00004635 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004636 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004637 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004638 "xmlParseEntityRef: expecting ';'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004639 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004640 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004641 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00004642 xmlFree(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004643 }
4644 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004645 return(ent);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004646}
4647
Daniel Veillard11e00581998-10-24 18:27:49 +00004648/**
4649 * xmlParsePEReference:
4650 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00004651 *
4652 * parse PEReference declarations
Daniel Veillard011b63c1999-06-02 17:44:04 +00004653 * The entity content is handled directly by pushing it's content as
4654 * a new input stream.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004655 *
4656 * [69] PEReference ::= '%' Name ';'
Daniel Veillard1e346af1999-02-22 10:33:01 +00004657 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004658 * [ WFC: No Recursion ]
4659 * TODO A parsed entity must not contain a recursive
4660 * reference to itself, either directly or indirectly.
4661 *
4662 * [ WFC: Entity Declared ]
4663 * In a document without any DTD, a document with only an internal DTD
4664 * subset which contains no parameter entity references, or a document
4665 * with "standalone='yes'", ... ... The declaration of a parameter
4666 * entity must precede any reference to it...
4667 *
4668 * [ VC: Entity Declared ]
4669 * In a document with an external subset or external parameter entities
4670 * with "standalone='no'", ... ... The declaration of a parameter entity
4671 * must precede any reference to it...
4672 *
4673 * [ WFC: In DTD ]
4674 * Parameter-entity references may only appear in the DTD.
4675 * NOTE: misleading but this is handled.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004676 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004677void
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004678xmlParsePEReference(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004679 xmlChar *name;
Daniel Veillard517752b1999-04-05 12:20:10 +00004680 xmlEntityPtr entity = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00004681 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004682
4683 if (CUR == '%') {
4684 NEXT;
4685 name = xmlParseName(ctxt);
4686 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004687 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004688 ctxt->sax->error(ctxt->userData,
4689 "xmlParsePEReference: no name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004690 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004691 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004692 } else {
4693 if (CUR == ';') {
4694 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004695 if ((ctxt->sax != NULL) &&
4696 (ctxt->sax->getParameterEntity != NULL))
4697 entity = ctxt->sax->getParameterEntity(ctxt->userData,
4698 name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004699 if (entity == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004700 /*
4701 * [ WFC: Entity Declared ]
4702 * In a document without any DTD, a document with only an
4703 * internal DTD subset which contains no parameter entity
4704 * references, or a document with "standalone='yes'", ...
4705 * ... The declaration of a parameter entity must precede
4706 * any reference to it...
4707 */
4708 if ((ctxt->standalone == 1) ||
4709 ((ctxt->hasExternalSubset == 0) &&
4710 (ctxt->hasPErefs == 0))) {
4711 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4712 ctxt->sax->error(ctxt->userData,
4713 "PEReference: %%%s; not found\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004714 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004715 ctxt->wellFormed = 0;
4716 } else {
4717 /*
4718 * [ VC: Entity Declared ]
4719 * In a document with an external subset or external
4720 * parameter entities with "standalone='no'", ...
4721 * ... The declaration of a parameter entity must precede
4722 * any reference to it...
4723 */
4724 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4725 ctxt->sax->warning(ctxt->userData,
4726 "PEReference: %%%s; not found\n", name);
4727 ctxt->valid = 0;
4728 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004729 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004730 /*
4731 * Internal checking in case the entity quest barfed
4732 */
4733 if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
4734 (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
4735 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4736 ctxt->sax->warning(ctxt->userData,
4737 "Internal: %%%s; is not a parameter entity\n", name);
4738 } else {
4739 input = xmlNewEntityInputStream(ctxt, entity);
4740 xmlPushInput(ctxt, input);
4741 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004742 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004743 ctxt->hasPErefs = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004744 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004745 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004746 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004747 "xmlParsePEReference: expecting ';'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004748 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004749 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004750 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00004751 xmlFree(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004752 }
4753 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004754}
4755
Daniel Veillard11e00581998-10-24 18:27:49 +00004756/**
4757 * xmlParseDocTypeDecl :
4758 * @ctxt: an XML parser context
4759 *
4760 * parse a DOCTYPE declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00004761 *
4762 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
4763 * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
Daniel Veillardb05deb71999-08-10 19:04:08 +00004764 *
4765 * [ VC: Root Element Type ]
4766 * The Name in the document type declaration must match the element
4767 * type of the root element.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004768 */
4769
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004770void
4771xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004772 xmlChar *name;
4773 xmlChar *ExternalID = NULL;
4774 xmlChar *URI = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004775
4776 /*
4777 * We know that '<!DOCTYPE' has been detected.
4778 */
4779 SKIP(9);
4780
4781 SKIP_BLANKS;
4782
4783 /*
4784 * Parse the DOCTYPE name.
4785 */
4786 name = xmlParseName(ctxt);
4787 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004788 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004789 ctxt->sax->error(ctxt->userData,
4790 "xmlParseDocTypeDecl : no DOCTYPE name !\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004791 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004792 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004793 }
4794
4795 SKIP_BLANKS;
4796
4797 /*
4798 * Check for SystemID and ExternalID
4799 */
Daniel Veillard1e346af1999-02-22 10:33:01 +00004800 URI = xmlParseExternalID(ctxt, &ExternalID, 1);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004801
4802 if ((URI != NULL) || (ExternalID != NULL)) {
4803 ctxt->hasExternalSubset = 1;
4804 }
4805
Daniel Veillard260a68f1998-08-13 03:39:55 +00004806 SKIP_BLANKS;
4807
Daniel Veillard011b63c1999-06-02 17:44:04 +00004808 /*
4809 * NOTE: the SAX callback may try to fetch the external subset
4810 * entity and fill it up !
4811 */
Daniel Veillard517752b1999-04-05 12:20:10 +00004812 if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004813 ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004814
4815 /*
4816 * Is there any DTD definition ?
4817 */
4818 if (CUR == '[') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004819 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004820 NEXT;
4821 /*
4822 * Parse the succession of Markup declarations and
4823 * PEReferences.
4824 * Subsequence (markupdecl | PEReference | S)*
4825 */
4826 while (CUR != ']') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004827 const xmlChar *check = CUR_PTR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004828 int cons = ctxt->input->consumed;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004829
4830 SKIP_BLANKS;
4831 xmlParseMarkupDecl(ctxt);
Daniel Veillardccb09631998-10-27 06:21:04 +00004832 xmlParsePEReference(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004833
Daniel Veillard011b63c1999-06-02 17:44:04 +00004834 /*
4835 * Pop-up of finished entities.
4836 */
4837 while ((CUR == 0) && (ctxt->inputNr > 1))
4838 xmlPopInput(ctxt);
4839
Daniel Veillardc26087b1999-08-30 11:23:51 +00004840 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004841 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4842 ctxt->sax->error(ctxt->userData,
4843 "xmlParseDocTypeDecl: error detected in Markup declaration\n");
4844 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004845 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004846 break;
4847 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004848 }
4849 if (CUR == ']') NEXT;
4850 }
4851
4852 /*
4853 * We should be at the end of the DOCTYPE declaration.
4854 */
4855 if (CUR != '>') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004856 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004857 ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004858 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004859 ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004860 }
4861 NEXT;
4862
4863 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00004864 * Cleanup
Daniel Veillard260a68f1998-08-13 03:39:55 +00004865 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00004866 if (URI != NULL) xmlFree(URI);
4867 if (ExternalID != NULL) xmlFree(ExternalID);
4868 if (name != NULL) xmlFree(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004869}
4870
Daniel Veillard11e00581998-10-24 18:27:49 +00004871/**
4872 * xmlParseAttribute:
4873 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004874 * @value: a xmlChar ** used to store the value of the attribute
Daniel Veillard11e00581998-10-24 18:27:49 +00004875 *
4876 * parse an attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00004877 *
4878 * [41] Attribute ::= Name Eq AttValue
4879 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004880 * [ WFC: No External Entity References ]
4881 * Attribute values cannot contain direct or indirect entity references
4882 * to external entities.
4883 *
4884 * [ WFC: No < in Attribute Values ]
4885 * The replacement text of any entity referred to directly or indirectly in
4886 * an attribute value (other than "&lt;") must not contain a <.
4887 *
4888 * [ VC: Attribute Value Type ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00004889 * The attribute must have been declared; the value must be of the type
Daniel Veillardb05deb71999-08-10 19:04:08 +00004890 * declared for it.
4891 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004892 * [25] Eq ::= S? '=' S?
4893 *
4894 * With namespace:
4895 *
4896 * [NS 11] Attribute ::= QName Eq AttValue
4897 *
4898 * Also the case QName == xmlns:??? is handled independently as a namespace
4899 * definition.
Daniel Veillard1e346af1999-02-22 10:33:01 +00004900 *
Daniel Veillard517752b1999-04-05 12:20:10 +00004901 * Returns the attribute name, and the value in *value.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004902 */
4903
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004904xmlChar *
4905xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
4906 xmlChar *name, *val;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004907
Daniel Veillard517752b1999-04-05 12:20:10 +00004908 *value = NULL;
4909 name = xmlParseName(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004910 if (name == NULL) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004911 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004912 ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004913 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004914 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillardccb09631998-10-27 06:21:04 +00004915 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004916 }
4917
4918 /*
4919 * read the value
4920 */
4921 SKIP_BLANKS;
4922 if (CUR == '=') {
4923 NEXT;
4924 SKIP_BLANKS;
Daniel Veillard517752b1999-04-05 12:20:10 +00004925 val = xmlParseAttValue(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004926 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004927 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004928 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004929 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004930 "Specification mandate value for attribute %s\n", name);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004931 ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004932 ctxt->wellFormed = 0;
Daniel Veillardccb09631998-10-27 06:21:04 +00004933 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004934 }
4935
Daniel Veillard517752b1999-04-05 12:20:10 +00004936 *value = val;
4937 return(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004938}
4939
Daniel Veillard11e00581998-10-24 18:27:49 +00004940/**
4941 * xmlParseStartTag:
4942 * @ctxt: an XML parser context
4943 *
4944 * parse a start of tag either for rule element or
4945 * EmptyElement. In both case we don't parse the tag closing chars.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004946 *
4947 * [40] STag ::= '<' Name (S Attribute)* S? '>'
4948 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004949 * [ WFC: Unique Att Spec ]
4950 * No attribute name may appear more than once in the same start-tag or
4951 * empty-element tag.
4952 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004953 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
4954 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004955 * [ WFC: Unique Att Spec ]
4956 * No attribute name may appear more than once in the same start-tag or
4957 * empty-element tag.
4958 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004959 * With namespace:
4960 *
4961 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
4962 *
4963 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
Daniel Veillard14fff061999-06-22 21:49:07 +00004964 *
4965 * Returns the element name parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +00004966 */
4967
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004968xmlChar *
Daniel Veillard1e346af1999-02-22 10:33:01 +00004969xmlParseStartTag(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004970 xmlChar *name;
4971 xmlChar *attname;
4972 xmlChar *attvalue;
4973 const xmlChar **atts = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00004974 int nbatts = 0;
4975 int maxatts = 0;
4976 int i;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004977
Daniel Veillard14fff061999-06-22 21:49:07 +00004978 if (CUR != '<') return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004979 NEXT;
4980
Daniel Veillard517752b1999-04-05 12:20:10 +00004981 name = xmlParseName(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004982 if (name == NULL) {
4983 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004984 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004985 "xmlParseStartTag: invalid element name\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004986 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004987 ctxt->wellFormed = 0;
Daniel Veillard14fff061999-06-22 21:49:07 +00004988 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004989 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004990
4991 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00004992 * Now parse the attributes, it ends up with the ending
4993 *
4994 * (S Attribute)* S?
4995 */
4996 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004997 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004998 while ((IS_CHAR(CUR)) &&
4999 (CUR != '>') &&
5000 ((CUR != '/') || (NXT(1) != '>'))) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005001 const xmlChar *q = CUR_PTR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005002 int cons = ctxt->input->consumed;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005003
Daniel Veillard517752b1999-04-05 12:20:10 +00005004 attname = xmlParseAttribute(ctxt, &attvalue);
5005 if ((attname != NULL) && (attvalue != NULL)) {
5006 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005007 * [ WFC: Unique Att Spec ]
5008 * No attribute name may appear more than once in the same
5009 * start-tag or empty-element tag.
Daniel Veillard517752b1999-04-05 12:20:10 +00005010 */
5011 for (i = 0; i < nbatts;i += 2) {
5012 if (!xmlStrcmp(atts[i], attname)) {
5013 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00005014 ctxt->sax->error(ctxt->userData,
5015 "Attribute %s redefined\n",
5016 attname);
Daniel Veillard517752b1999-04-05 12:20:10 +00005017 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005018 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
Daniel Veillard6454aec1999-09-02 22:04:43 +00005019 xmlFree(attname);
5020 xmlFree(attvalue);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005021 goto failed;
Daniel Veillard517752b1999-04-05 12:20:10 +00005022 }
5023 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005024
Daniel Veillard517752b1999-04-05 12:20:10 +00005025 /*
5026 * Add the pair to atts
5027 */
5028 if (atts == NULL) {
5029 maxatts = 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005030 atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
Daniel Veillard517752b1999-04-05 12:20:10 +00005031 if (atts == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00005032 fprintf(stderr, "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005033 maxatts * (long)sizeof(xmlChar *));
Daniel Veillard14fff061999-06-22 21:49:07 +00005034 return(NULL);
Daniel Veillard517752b1999-04-05 12:20:10 +00005035 }
5036 } else if (nbatts + 2 < maxatts) {
5037 maxatts *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005038 atts = (const xmlChar **) xmlRealloc(atts,
5039 maxatts * sizeof(xmlChar *));
Daniel Veillard517752b1999-04-05 12:20:10 +00005040 if (atts == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00005041 fprintf(stderr, "realloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005042 maxatts * (long)sizeof(xmlChar *));
Daniel Veillard14fff061999-06-22 21:49:07 +00005043 return(NULL);
Daniel Veillard517752b1999-04-05 12:20:10 +00005044 }
5045 }
5046 atts[nbatts++] = attname;
5047 atts[nbatts++] = attvalue;
5048 atts[nbatts] = NULL;
5049 atts[nbatts + 1] = NULL;
5050 }
5051
Daniel Veillardb96e6431999-08-29 21:02:19 +00005052failed:
Daniel Veillard517752b1999-04-05 12:20:10 +00005053 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005054 if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005055 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005056 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00005057 "xmlParseStartTag: problem parsing attributes\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005058 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005059 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005060 break;
5061 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005062 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005063 }
5064
5065 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00005066 * SAX: Start of Element !
5067 */
Daniel Veillard517752b1999-04-05 12:20:10 +00005068 if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005069 ctxt->sax->startElement(ctxt->userData, name, atts);
Daniel Veillard517752b1999-04-05 12:20:10 +00005070
Daniel Veillard517752b1999-04-05 12:20:10 +00005071 if (atts != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005072 for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005073 xmlFree(atts);
Daniel Veillard517752b1999-04-05 12:20:10 +00005074 }
Daniel Veillard14fff061999-06-22 21:49:07 +00005075 return(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005076}
5077
Daniel Veillard11e00581998-10-24 18:27:49 +00005078/**
5079 * xmlParseEndTag:
5080 * @ctxt: an XML parser context
Daniel Veillard14fff061999-06-22 21:49:07 +00005081 * @tagname: the tag name as parsed in the opening tag.
Daniel Veillard11e00581998-10-24 18:27:49 +00005082 *
5083 * parse an end of tag
Daniel Veillard260a68f1998-08-13 03:39:55 +00005084 *
5085 * [42] ETag ::= '</' Name S? '>'
5086 *
5087 * With namespace
5088 *
Daniel Veillard517752b1999-04-05 12:20:10 +00005089 * [NS 9] ETag ::= '</' QName S? '>'
Daniel Veillard260a68f1998-08-13 03:39:55 +00005090 */
5091
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005092void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005093xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlChar *tagname) {
5094 xmlChar *name;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005095
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005096 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005097 if ((CUR != '<') || (NXT(1) != '/')) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005098 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005099 ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005100 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005101 ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005102 return;
5103 }
5104 SKIP(2);
5105
Daniel Veillard517752b1999-04-05 12:20:10 +00005106 name = xmlParseName(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005107
5108 /*
5109 * We should definitely be at the ending "S? '>'" part
5110 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005111 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005112 SKIP_BLANKS;
5113 if ((!IS_CHAR(CUR)) || (CUR != '>')) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005114 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005115 ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005116 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005117 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005118 } else
5119 NEXT;
5120
Daniel Veillard517752b1999-04-05 12:20:10 +00005121 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005122 * [ WFC: Element Type Match ]
5123 * The Name in an element's end-tag must match the element type in the
5124 * start-tag.
5125 *
Daniel Veillard14fff061999-06-22 21:49:07 +00005126 */
5127 if (xmlStrcmp(name, tagname)) {
5128 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5129 ctxt->sax->error(ctxt->userData,
5130 "Opening and ending tag mismatch: %s and %s\n", tagname, name);
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005131
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005132 ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
Daniel Veillard14fff061999-06-22 21:49:07 +00005133 ctxt->wellFormed = 0;
5134 }
5135
5136 /*
Daniel Veillard517752b1999-04-05 12:20:10 +00005137 * SAX: End of Tag
5138 */
5139 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005140 ctxt->sax->endElement(ctxt->userData, name);
Daniel Veillard517752b1999-04-05 12:20:10 +00005141
5142 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00005143 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +00005144
Daniel Veillard260a68f1998-08-13 03:39:55 +00005145 return;
5146}
5147
Daniel Veillard11e00581998-10-24 18:27:49 +00005148/**
5149 * xmlParseCDSect:
5150 * @ctxt: an XML parser context
5151 *
5152 * Parse escaped pure raw content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005153 *
5154 * [18] CDSect ::= CDStart CData CDEnd
5155 *
5156 * [19] CDStart ::= '<![CDATA['
5157 *
5158 * [20] Data ::= (Char* - (Char* ']]>' Char*))
5159 *
5160 * [21] CDEnd ::= ']]>'
5161 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005162void
5163xmlParseCDSect(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005164 const xmlChar *base;
5165 xmlChar r, s;
5166 xmlChar cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005167
Daniel Veillardb05deb71999-08-10 19:04:08 +00005168 if ((NXT(0) == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00005169 (NXT(2) == '[') && (NXT(3) == 'C') &&
5170 (NXT(4) == 'D') && (NXT(5) == 'A') &&
5171 (NXT(6) == 'T') && (NXT(7) == 'A') &&
5172 (NXT(8) == '[')) {
5173 SKIP(9);
5174 } else
5175 return;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005176
5177 ctxt->instate = XML_PARSER_CDATA_SECTION;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005178 base = CUR_PTR;
5179 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005180 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005181 ctxt->sax->error(ctxt->userData,
5182 "CData section not finished\n%.50s\n", base);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005183 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005184 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005185 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005186 return;
5187 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00005188 r = CUR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005189 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005190 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005191 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005192 ctxt->sax->error(ctxt->userData,
5193 "CData section not finished\n%.50s\n", base);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005194 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005195 ctxt->wellFormed = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005196 ctxt->instate = XML_PARSER_CONTENT;
5197 return;
5198 }
5199 s = CUR;
5200 NEXT;
5201 cur = CUR;
5202 while (IS_CHAR(cur) &&
5203 ((r != ']') || (s != ']') || (cur != '>'))) {
5204 r = s;
5205 s = cur;
5206 NEXT;
5207 cur = CUR;
5208 }
5209 ctxt->instate = XML_PARSER_CONTENT;
5210 if (!IS_CHAR(CUR)) {
5211 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005212 ctxt->sax->error(ctxt->userData,
5213 "CData section not finished\n%.50s\n", base);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005214 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005215 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005216 return;
5217 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005218 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005219
5220 /*
5221 * Ok the segment [base CUR_PTR] is to be consumed as chars.
5222 */
5223 if (ctxt->sax != NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005224 if (ctxt->sax->cdataBlock != NULL)
5225 ctxt->sax->cdataBlock(ctxt->userData, base, (CUR_PTR - base) - 3);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005226 }
5227}
5228
Daniel Veillard11e00581998-10-24 18:27:49 +00005229/**
5230 * xmlParseContent:
5231 * @ctxt: an XML parser context
5232 *
5233 * Parse a content:
Daniel Veillard260a68f1998-08-13 03:39:55 +00005234 *
5235 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
5236 */
5237
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005238void
5239xmlParseContent(xmlParserCtxtPtr ctxt) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005240 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005241 while ((CUR != '<') || (NXT(1) != '/')) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005242 const xmlChar *test = CUR_PTR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005243 int cons = ctxt->input->consumed;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005244 xmlChar tok = ctxt->token;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005245
5246 /*
5247 * First case : a Processing Instruction.
5248 */
5249 if ((CUR == '<') && (NXT(1) == '?')) {
5250 xmlParsePI(ctxt);
5251 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005252
Daniel Veillard260a68f1998-08-13 03:39:55 +00005253 /*
5254 * Second case : a CDSection
5255 */
5256 else if ((CUR == '<') && (NXT(1) == '!') &&
5257 (NXT(2) == '[') && (NXT(3) == 'C') &&
5258 (NXT(4) == 'D') && (NXT(5) == 'A') &&
5259 (NXT(6) == 'T') && (NXT(7) == 'A') &&
5260 (NXT(8) == '[')) {
5261 xmlParseCDSect(ctxt);
5262 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005263
Daniel Veillard260a68f1998-08-13 03:39:55 +00005264 /*
5265 * Third case : a comment
5266 */
5267 else if ((CUR == '<') && (NXT(1) == '!') &&
5268 (NXT(2) == '-') && (NXT(3) == '-')) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00005269 xmlParseComment(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005270 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005271 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005272
Daniel Veillard260a68f1998-08-13 03:39:55 +00005273 /*
5274 * Fourth case : a sub-element.
5275 */
5276 else if (CUR == '<') {
Daniel Veillard517752b1999-04-05 12:20:10 +00005277 xmlParseElement(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005278 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005279
Daniel Veillard260a68f1998-08-13 03:39:55 +00005280 /*
Daniel Veillardccb09631998-10-27 06:21:04 +00005281 * Fifth case : a reference. If if has not been resolved,
5282 * parsing returns it's Name, create the node
Daniel Veillard260a68f1998-08-13 03:39:55 +00005283 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00005284
Daniel Veillard260a68f1998-08-13 03:39:55 +00005285 else if (CUR == '&') {
Daniel Veillard011b63c1999-06-02 17:44:04 +00005286 xmlParseReference(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005287 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005288
Daniel Veillard260a68f1998-08-13 03:39:55 +00005289 /*
5290 * Last case, text. Note that References are handled directly.
5291 */
5292 else {
5293 xmlParseCharData(ctxt, 0);
5294 }
5295
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005296 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005297 /*
5298 * Pop-up of finished entities.
5299 */
Daniel Veillardbc50b591999-03-01 12:28:53 +00005300 while ((CUR == 0) && (ctxt->inputNr > 1))
5301 xmlPopInput(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005302
Daniel Veillardb96e6431999-08-29 21:02:19 +00005303 if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
5304 (tok == ctxt->token)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005305 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005306 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005307 "detected an error in element content\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005308 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005309 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005310 break;
5311 }
5312 }
5313}
5314
Daniel Veillard11e00581998-10-24 18:27:49 +00005315/**
5316 * xmlParseElement:
5317 * @ctxt: an XML parser context
5318 *
5319 * parse an XML element, this is highly recursive
Daniel Veillard260a68f1998-08-13 03:39:55 +00005320 *
5321 * [39] element ::= EmptyElemTag | STag content ETag
5322 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005323 * [ WFC: Element Type Match ]
5324 * The Name in an element's end-tag must match the element type in the
5325 * start-tag.
5326 *
5327 * [ VC: Element Valid ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00005328 * An element is valid if there is a declaration matching elementdecl
Daniel Veillardb05deb71999-08-10 19:04:08 +00005329 * where the Name matches the element type and one of the following holds:
5330 * - The declaration matches EMPTY and the element has no content.
5331 * - The declaration matches children and the sequence of child elements
5332 * belongs to the language generated by the regular expression in the
5333 * content model, with optional white space (characters matching the
5334 * nonterminal S) between each pair of child elements.
5335 * - The declaration matches Mixed and the content consists of character
5336 * data and child elements whose types match names in the content model.
5337 * - The declaration matches ANY, and the types of any child elements have
5338 * been declared.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005339 */
5340
Daniel Veillard517752b1999-04-05 12:20:10 +00005341void
Daniel Veillard1e346af1999-02-22 10:33:01 +00005342xmlParseElement(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005343 const xmlChar *openTag = CUR_PTR;
5344 xmlChar *name;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005345 xmlParserNodeInfo node_info;
Daniel Veillardc26087b1999-08-30 11:23:51 +00005346 xmlNodePtr ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005347
5348 /* Capture start position */
Daniel Veillardc26087b1999-08-30 11:23:51 +00005349 if (ctxt->record_info) {
5350 node_info.begin_pos = ctxt->input->consumed +
5351 (CUR_PTR - ctxt->input->base);
5352 node_info.begin_line = ctxt->input->line;
5353 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005354
Daniel Veillard14fff061999-06-22 21:49:07 +00005355 name = xmlParseStartTag(ctxt);
5356 if (name == NULL) {
5357 return;
5358 }
Daniel Veillardc26087b1999-08-30 11:23:51 +00005359 ret = ctxt->node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005360
5361 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005362 * [ VC: Root Element Type ]
5363 * The Name in the document type declaration must match the element
5364 * type of the root element.
5365 */
5366 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
5367 ctxt->node && (ctxt->node == ctxt->myDoc->root))
5368 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
5369
5370 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00005371 * Check for an Empty Element.
5372 */
5373 if ((CUR == '/') && (NXT(1) == '>')) {
5374 SKIP(2);
Daniel Veillard517752b1999-04-05 12:20:10 +00005375 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
Daniel Veillard14fff061999-06-22 21:49:07 +00005376 ctxt->sax->endElement(ctxt->userData, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005377 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +00005378 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005379 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005380 if (CUR == '>') {
5381 NEXT;
5382 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005383 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005384 ctxt->sax->error(ctxt->userData,
5385 "Couldn't find end of Start Tag\n%.30s\n",
Daniel Veillard242590e1998-11-13 18:04:35 +00005386 openTag);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005387 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005388 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005389
5390 /*
5391 * end of parsing of this node.
5392 */
5393 nodePop(ctxt);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005394 xmlFree(name);
Daniel Veillardc26087b1999-08-30 11:23:51 +00005395
5396 /*
5397 * Capture end position and add node
5398 */
5399 if ( ret != NULL && ctxt->record_info ) {
5400 node_info.end_pos = ctxt->input->consumed +
5401 (CUR_PTR - ctxt->input->base);
5402 node_info.end_line = ctxt->input->line;
5403 node_info.node = ret;
5404 xmlParserAddNodeInfo(ctxt, &node_info);
5405 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005406 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005407 }
5408
5409 /*
5410 * Parse the content of the element:
5411 */
5412 xmlParseContent(ctxt);
5413 if (!IS_CHAR(CUR)) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005414 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005415 ctxt->sax->error(ctxt->userData,
Daniel Veillard242590e1998-11-13 18:04:35 +00005416 "Premature end of data in tag %.30s\n", openTag);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005417 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005418 ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005419
5420 /*
5421 * end of parsing of this node.
5422 */
5423 nodePop(ctxt);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005424 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +00005425 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005426 }
5427
5428 /*
5429 * parse the end of tag: '</' should be here.
5430 */
Daniel Veillard14fff061999-06-22 21:49:07 +00005431 xmlParseEndTag(ctxt, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005432 xmlFree(name);
Daniel Veillardc26087b1999-08-30 11:23:51 +00005433
5434 /*
5435 * Capture end position and add node
5436 */
5437 if ( ret != NULL && ctxt->record_info ) {
5438 node_info.end_pos = ctxt->input->consumed +
5439 (CUR_PTR - ctxt->input->base);
5440 node_info.end_line = ctxt->input->line;
5441 node_info.node = ret;
5442 xmlParserAddNodeInfo(ctxt, &node_info);
5443 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005444}
5445
Daniel Veillard11e00581998-10-24 18:27:49 +00005446/**
5447 * xmlParseVersionNum:
5448 * @ctxt: an XML parser context
5449 *
5450 * parse the XML version value.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005451 *
5452 * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
Daniel Veillard1e346af1999-02-22 10:33:01 +00005453 *
5454 * Returns the string giving the XML version number, or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00005455 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005456xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005457xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005458 const xmlChar *q = CUR_PTR;
5459 xmlChar *ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005460
5461 while (IS_CHAR(CUR) &&
5462 (((CUR >= 'a') && (CUR <= 'z')) ||
5463 ((CUR >= 'A') && (CUR <= 'Z')) ||
5464 ((CUR >= '0') && (CUR <= '9')) ||
5465 (CUR == '_') || (CUR == '.') ||
5466 (CUR == ':') || (CUR == '-'))) NEXT;
5467 ret = xmlStrndup(q, CUR_PTR - q);
5468 return(ret);
5469}
5470
Daniel Veillard11e00581998-10-24 18:27:49 +00005471/**
5472 * xmlParseVersionInfo:
5473 * @ctxt: an XML parser context
5474 *
5475 * parse the XML version.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005476 *
5477 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
5478 *
5479 * [25] Eq ::= S? '=' S?
Daniel Veillard11e00581998-10-24 18:27:49 +00005480 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005481 * Returns the version string, e.g. "1.0"
Daniel Veillard260a68f1998-08-13 03:39:55 +00005482 */
5483
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005484xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005485xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005486 xmlChar *version = NULL;
5487 const xmlChar *q;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005488
5489 if ((CUR == 'v') && (NXT(1) == 'e') &&
5490 (NXT(2) == 'r') && (NXT(3) == 's') &&
5491 (NXT(4) == 'i') && (NXT(5) == 'o') &&
5492 (NXT(6) == 'n')) {
5493 SKIP(7);
5494 SKIP_BLANKS;
5495 if (CUR != '=') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005496 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005497 ctxt->sax->error(ctxt->userData,
5498 "xmlParseVersionInfo : expected '='\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005499 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005500 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005501 return(NULL);
5502 }
5503 NEXT;
5504 SKIP_BLANKS;
5505 if (CUR == '"') {
5506 NEXT;
5507 q = CUR_PTR;
5508 version = xmlParseVersionNum(ctxt);
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005509 if (CUR != '"') {
5510 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005511 ctxt->sax->error(ctxt->userData,
5512 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005513 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005514 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005515 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005516 NEXT;
5517 } else if (CUR == '\''){
5518 NEXT;
5519 q = CUR_PTR;
5520 version = xmlParseVersionNum(ctxt);
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005521 if (CUR != '\'') {
5522 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005523 ctxt->sax->error(ctxt->userData,
5524 "String not closed\n%.50s\n", q);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005525 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005526 ctxt->wellFormed = 0;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005527 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005528 NEXT;
5529 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005530 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005531 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005532 "xmlParseVersionInfo : expected ' or \"\n");
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005533 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005534 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005535 }
5536 }
5537 return(version);
5538}
5539
Daniel Veillard11e00581998-10-24 18:27:49 +00005540/**
5541 * xmlParseEncName:
5542 * @ctxt: an XML parser context
5543 *
5544 * parse the XML encoding name
Daniel Veillard260a68f1998-08-13 03:39:55 +00005545 *
5546 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
Daniel Veillard11e00581998-10-24 18:27:49 +00005547 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005548 * Returns the encoding name value or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00005549 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005550xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005551xmlParseEncName(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005552 const xmlChar *q = CUR_PTR;
5553 xmlChar *ret = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005554
5555 if (((CUR >= 'a') && (CUR <= 'z')) ||
5556 ((CUR >= 'A') && (CUR <= 'Z'))) {
5557 NEXT;
5558 while (IS_CHAR(CUR) &&
5559 (((CUR >= 'a') && (CUR <= 'z')) ||
5560 ((CUR >= 'A') && (CUR <= 'Z')) ||
5561 ((CUR >= '0') && (CUR <= '9')) ||
5562 (CUR == '-'))) NEXT;
5563 ret = xmlStrndup(q, CUR_PTR - q);
5564 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005565 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005566 ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005567 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005568 ctxt->errNo = XML_ERR_ENCODING_NAME;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005569 }
5570 return(ret);
5571}
5572
Daniel Veillard11e00581998-10-24 18:27:49 +00005573/**
5574 * xmlParseEncodingDecl:
5575 * @ctxt: an XML parser context
5576 *
5577 * parse the XML encoding declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00005578 *
5579 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'")
Daniel Veillard11e00581998-10-24 18:27:49 +00005580 *
5581 * TODO: this should setup the conversion filters.
5582 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005583 * Returns the encoding value or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00005584 */
5585
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005586xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005587xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005588 xmlChar *encoding = NULL;
5589 const xmlChar *q;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005590
5591 SKIP_BLANKS;
5592 if ((CUR == 'e') && (NXT(1) == 'n') &&
5593 (NXT(2) == 'c') && (NXT(3) == 'o') &&
5594 (NXT(4) == 'd') && (NXT(5) == 'i') &&
5595 (NXT(6) == 'n') && (NXT(7) == 'g')) {
5596 SKIP(8);
5597 SKIP_BLANKS;
5598 if (CUR != '=') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005599 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005600 ctxt->sax->error(ctxt->userData,
5601 "xmlParseEncodingDecl : expected '='\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005602 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005603 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005604 return(NULL);
5605 }
5606 NEXT;
5607 SKIP_BLANKS;
5608 if (CUR == '"') {
5609 NEXT;
5610 q = CUR_PTR;
5611 encoding = xmlParseEncName(ctxt);
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005612 if (CUR != '"') {
5613 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005614 ctxt->sax->error(ctxt->userData,
5615 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005616 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005617 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005618 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005619 NEXT;
5620 } else if (CUR == '\''){
5621 NEXT;
5622 q = CUR_PTR;
5623 encoding = xmlParseEncName(ctxt);
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005624 if (CUR != '\'') {
5625 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005626 ctxt->sax->error(ctxt->userData,
5627 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005628 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005629 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005630 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005631 NEXT;
5632 } else if (CUR == '"'){
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005633 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005634 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005635 "xmlParseEncodingDecl : expected ' or \"\n");
5636 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005637 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005638 }
5639 }
5640 return(encoding);
5641}
5642
Daniel Veillard11e00581998-10-24 18:27:49 +00005643/**
5644 * xmlParseSDDecl:
5645 * @ctxt: an XML parser context
5646 *
5647 * parse the XML standalone declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00005648 *
5649 * [32] SDDecl ::= S 'standalone' Eq
5650 * (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
Daniel Veillard1e346af1999-02-22 10:33:01 +00005651 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005652 * [ VC: Standalone Document Declaration ]
5653 * TODO The standalone document declaration must have the value "no"
5654 * if any external markup declarations contain declarations of:
5655 * - attributes with default values, if elements to which these
5656 * attributes apply appear in the document without specifications
5657 * of values for these attributes, or
5658 * - entities (other than amp, lt, gt, apos, quot), if references
5659 * to those entities appear in the document, or
5660 * - attributes with values subject to normalization, where the
5661 * attribute appears in the document with a value which will change
5662 * as a result of normalization, or
5663 * - element types with element content, if white space occurs directly
5664 * within any instance of those types.
5665 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005666 * Returns 1 if standalone, 0 otherwise
Daniel Veillard260a68f1998-08-13 03:39:55 +00005667 */
5668
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005669int
5670xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005671 int standalone = -1;
5672
5673 SKIP_BLANKS;
5674 if ((CUR == 's') && (NXT(1) == 't') &&
5675 (NXT(2) == 'a') && (NXT(3) == 'n') &&
5676 (NXT(4) == 'd') && (NXT(5) == 'a') &&
5677 (NXT(6) == 'l') && (NXT(7) == 'o') &&
5678 (NXT(8) == 'n') && (NXT(9) == 'e')) {
5679 SKIP(10);
Daniel Veillard011b63c1999-06-02 17:44:04 +00005680 SKIP_BLANKS;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005681 if (CUR != '=') {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005682 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005683 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005684 "XML standalone declaration : expected '='\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005685 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005686 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005687 return(standalone);
5688 }
5689 NEXT;
5690 SKIP_BLANKS;
5691 if (CUR == '\''){
5692 NEXT;
5693 if ((CUR == 'n') && (NXT(1) == 'o')) {
5694 standalone = 0;
5695 SKIP(2);
5696 } else if ((CUR == 'y') && (NXT(1) == 'e') &&
5697 (NXT(2) == 's')) {
5698 standalone = 1;
5699 SKIP(3);
5700 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005701 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005702 ctxt->sax->error(ctxt->userData,
5703 "standalone accepts only 'yes' or 'no'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005704 ctxt->errNo = XML_ERR_STANDALONE_VALUE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005705 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005706 }
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005707 if (CUR != '\'') {
5708 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005709 ctxt->sax->error(ctxt->userData, "String not closed\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005710 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005711 ctxt->wellFormed = 0;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005712 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005713 NEXT;
5714 } else if (CUR == '"'){
5715 NEXT;
5716 if ((CUR == 'n') && (NXT(1) == 'o')) {
5717 standalone = 0;
5718 SKIP(2);
5719 } else if ((CUR == 'y') && (NXT(1) == 'e') &&
5720 (NXT(2) == 's')) {
5721 standalone = 1;
5722 SKIP(3);
5723 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005724 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005725 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005726 "standalone accepts only 'yes' or 'no'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005727 ctxt->errNo = XML_ERR_STANDALONE_VALUE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005728 ctxt->wellFormed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005729 }
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005730 if (CUR != '"') {
5731 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005732 ctxt->sax->error(ctxt->userData, "String not closed\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005733 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005734 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005735 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00005736 NEXT;
5737 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005738 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005739 ctxt->sax->error(ctxt->userData,
5740 "Standalone value not found\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005741 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005742 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005743 }
5744 }
5745 return(standalone);
5746}
5747
Daniel Veillard11e00581998-10-24 18:27:49 +00005748/**
5749 * xmlParseXMLDecl:
5750 * @ctxt: an XML parser context
5751 *
5752 * parse an XML declaration header
Daniel Veillard260a68f1998-08-13 03:39:55 +00005753 *
5754 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
5755 */
5756
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005757void
5758xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005759 xmlChar *version;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005760
5761 /*
5762 * We know that '<?xml' is here.
5763 */
5764 SKIP(5);
5765
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005766 if (!IS_BLANK(CUR)) {
5767 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005768 ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005769 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005770 ctxt->wellFormed = 0;
5771 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005772 SKIP_BLANKS;
5773
5774 /*
5775 * We should have the VersionInfo here.
5776 */
5777 version = xmlParseVersionInfo(ctxt);
5778 if (version == NULL)
5779 version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillard517752b1999-04-05 12:20:10 +00005780 ctxt->version = xmlStrdup(version);
Daniel Veillard6454aec1999-09-02 22:04:43 +00005781 xmlFree(version);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005782
5783 /*
5784 * We may have the encoding declaration
5785 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005786 if (!IS_BLANK(CUR)) {
5787 if ((CUR == '?') && (NXT(1) == '>')) {
5788 SKIP(2);
5789 return;
5790 }
5791 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005792 ctxt->sax->error(ctxt->userData, "Blank needed here\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005793 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005794 ctxt->wellFormed = 0;
5795 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005796 ctxt->encoding = xmlParseEncodingDecl(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005797
5798 /*
5799 * We may have the standalone status.
5800 */
Daniel Veillard517752b1999-04-05 12:20:10 +00005801 if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005802 if ((CUR == '?') && (NXT(1) == '>')) {
5803 SKIP(2);
5804 return;
5805 }
5806 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005807 ctxt->sax->error(ctxt->userData, "Blank needed here\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005808 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005809 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005810 }
5811 SKIP_BLANKS;
Daniel Veillard517752b1999-04-05 12:20:10 +00005812 ctxt->standalone = xmlParseSDDecl(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005813
5814 SKIP_BLANKS;
5815 if ((CUR == '?') && (NXT(1) == '>')) {
5816 SKIP(2);
5817 } else if (CUR == '>') {
5818 /* Deprecated old WD ... */
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005819 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005820 ctxt->sax->error(ctxt->userData,
5821 "XML declaration must end-up with '?>'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005822 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005823 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005824 NEXT;
5825 } else {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005826 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005827 ctxt->sax->error(ctxt->userData,
5828 "parsing XML declaration: '?>' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005829 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005830 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005831 MOVETO_ENDTAG(CUR_PTR);
5832 NEXT;
5833 }
5834}
5835
Daniel Veillard11e00581998-10-24 18:27:49 +00005836/**
5837 * xmlParseMisc:
5838 * @ctxt: an XML parser context
5839 *
5840 * parse an XML Misc* optionnal field.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005841 *
5842 * [27] Misc ::= Comment | PI | S
5843 */
5844
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005845void
5846xmlParseMisc(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005847 while (((CUR == '<') && (NXT(1) == '?')) ||
5848 ((CUR == '<') && (NXT(1) == '!') &&
5849 (NXT(2) == '-') && (NXT(3) == '-')) ||
5850 IS_BLANK(CUR)) {
5851 if ((CUR == '<') && (NXT(1) == '?')) {
5852 xmlParsePI(ctxt);
5853 } else if (IS_BLANK(CUR)) {
5854 NEXT;
5855 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00005856 xmlParseComment(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005857 }
5858}
5859
Daniel Veillard11e00581998-10-24 18:27:49 +00005860/**
5861 * xmlParseDocument :
5862 * @ctxt: an XML parser context
5863 *
5864 * parse an XML document (and build a tree if using the standard SAX
5865 * interface).
Daniel Veillard260a68f1998-08-13 03:39:55 +00005866 *
5867 * [1] document ::= prolog element Misc*
5868 *
5869 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
Daniel Veillard11e00581998-10-24 18:27:49 +00005870 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005871 * Returns 0, -1 in case of error. the parser context is augmented
Daniel Veillard11e00581998-10-24 18:27:49 +00005872 * as a result of the parsing.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005873 */
5874
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005875int
5876xmlParseDocument(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005877 xmlDefaultSAXHandlerInit();
5878
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005879 GROW;
5880
Daniel Veillard260a68f1998-08-13 03:39:55 +00005881 /*
5882 * SAX: beginning of the document processing.
5883 */
Daniel Veillard517752b1999-04-05 12:20:10 +00005884 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
Daniel Veillard27d88741999-05-29 11:51:49 +00005885 ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005886
5887 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +00005888 * TODO We should check for encoding here and plug-in some
5889 * conversion code !!!!
Daniel Veillard260a68f1998-08-13 03:39:55 +00005890 */
5891
5892 /*
5893 * Wipe out everything which is before the first '<'
5894 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005895 if (IS_BLANK(CUR)) {
5896 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005897 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005898 "Extra spaces at the beginning of the document are not allowed\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005899 ctxt->errNo = XML_ERR_DOCUMENT_START;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005900 ctxt->wellFormed = 0;
5901 SKIP_BLANKS;
5902 }
5903
5904 if (CUR == 0) {
5905 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005906 ctxt->sax->error(ctxt->userData, "Document is empty\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005907 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005908 ctxt->wellFormed = 0;
5909 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005910
5911 /*
5912 * Check for the XMLDecl in the Prolog.
5913 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005914 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005915 if ((CUR == '<') && (NXT(1) == '?') &&
5916 (NXT(2) == 'x') && (NXT(3) == 'm') &&
5917 (NXT(4) == 'l')) {
5918 xmlParseXMLDecl(ctxt);
5919 /* SKIP_EOL(cur); */
5920 SKIP_BLANKS;
5921 } else if ((CUR == '<') && (NXT(1) == '?') &&
5922 (NXT(2) == 'X') && (NXT(3) == 'M') &&
5923 (NXT(4) == 'L')) {
5924 /*
5925 * The first drafts were using <?XML and the final W3C REC
5926 * now use <?xml ...
5927 */
5928 xmlParseXMLDecl(ctxt);
5929 /* SKIP_EOL(cur); */
5930 SKIP_BLANKS;
5931 } else {
Daniel Veillard517752b1999-04-05 12:20:10 +00005932 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005933 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005934 if ((ctxt->sax) && (ctxt->sax->startDocument))
Daniel Veillard27d88741999-05-29 11:51:49 +00005935 ctxt->sax->startDocument(ctxt->userData);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005936
5937 /*
5938 * The Misc part of the Prolog
5939 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005940 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005941 xmlParseMisc(ctxt);
5942
5943 /*
5944 * Then possibly doc type declaration(s) and more Misc
5945 * (doctypedecl Misc*)?
5946 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005947 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005948 if ((CUR == '<') && (NXT(1) == '!') &&
5949 (NXT(2) == 'D') && (NXT(3) == 'O') &&
5950 (NXT(4) == 'C') && (NXT(5) == 'T') &&
5951 (NXT(6) == 'Y') && (NXT(7) == 'P') &&
5952 (NXT(8) == 'E')) {
5953 xmlParseDocTypeDecl(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005954 ctxt->instate = XML_PARSER_PROLOG;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005955 xmlParseMisc(ctxt);
5956 }
5957
5958 /*
5959 * Time to start parsing the tree itself
5960 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005961 GROW;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005962 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard517752b1999-04-05 12:20:10 +00005963 xmlParseElement(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005964 ctxt->instate = XML_PARSER_EPILOG;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005965
5966 /*
5967 * The Misc part at the end
5968 */
5969 xmlParseMisc(ctxt);
5970
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005971 if (CUR != 0) {
5972 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005973 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005974 "Extra content at the end of the document\n");
5975 ctxt->wellFormed = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005976 ctxt->errNo = XML_ERR_DOCUMENT_END;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005977 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00005978 ctxt->instate = XML_PARSER_EOF;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005979
Daniel Veillard260a68f1998-08-13 03:39:55 +00005980 /*
5981 * SAX: end of the document processing.
5982 */
Daniel Veillard517752b1999-04-05 12:20:10 +00005983 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005984 ctxt->sax->endDocument(ctxt->userData);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005985 if (! ctxt->wellFormed) return(-1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005986 return(0);
5987}
5988
Daniel Veillardb05deb71999-08-10 19:04:08 +00005989/************************************************************************
5990 * *
5991 * I/O front end functions to the parser *
5992 * *
5993 ************************************************************************/
5994
Daniel Veillard11e00581998-10-24 18:27:49 +00005995/**
Daniel Veillardbe70ff71999-07-05 16:50:46 +00005996 * xmlCreateDocParserCtxt :
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005997 * @cur: a pointer to an array of xmlChar
Daniel Veillardd692aa41999-02-28 21:54:31 +00005998 *
5999 * Create a parser context for an XML in-memory document.
6000 *
6001 * Returns the new parser context or NULL
6002 */
6003xmlParserCtxtPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006004xmlCreateDocParserCtxt(xmlChar *cur) {
Daniel Veillardd692aa41999-02-28 21:54:31 +00006005 xmlParserCtxtPtr ctxt;
6006 xmlParserInputPtr input;
Daniel Veillard27d88741999-05-29 11:51:49 +00006007 xmlCharEncoding enc;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006008
Daniel Veillardb05deb71999-08-10 19:04:08 +00006009 ctxt = xmlNewParserCtxt();
Daniel Veillardd692aa41999-02-28 21:54:31 +00006010 if (ctxt == NULL) {
Daniel Veillardd692aa41999-02-28 21:54:31 +00006011 return(NULL);
6012 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00006013 input = xmlNewInputStream(ctxt);
Daniel Veillardd692aa41999-02-28 21:54:31 +00006014 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00006015 xmlFreeParserCtxt(ctxt);
Daniel Veillardd692aa41999-02-28 21:54:31 +00006016 return(NULL);
6017 }
6018
Daniel Veillard27d88741999-05-29 11:51:49 +00006019 /*
6020 * plug some encoding conversion routines here. !!!
6021 */
6022 enc = xmlDetectCharEncoding(cur);
6023 xmlSwitchEncoding(ctxt, enc);
6024
Daniel Veillardd692aa41999-02-28 21:54:31 +00006025 input->base = cur;
6026 input->cur = cur;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006027
6028 inputPush(ctxt, input);
6029 return(ctxt);
6030}
6031
6032/**
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006033 * xmlSAXParseDoc :
6034 * @sax: the SAX handler block
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006035 * @cur: a pointer to an array of xmlChar
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006036 * @recovery: work in recovery mode, i.e. tries to read no Well Formed
6037 * documents
Daniel Veillard11e00581998-10-24 18:27:49 +00006038 *
6039 * parse an XML in-memory document and build a tree.
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006040 * It use the given SAX function block to handle the parsing callback.
6041 * If sax is NULL, fallback to the default DOM tree building routines.
Daniel Veillard11e00581998-10-24 18:27:49 +00006042 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006043 * Returns the resulting document tree
Daniel Veillard260a68f1998-08-13 03:39:55 +00006044 */
6045
Daniel Veillard1e346af1999-02-22 10:33:01 +00006046xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006047xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006048 xmlDocPtr ret;
6049 xmlParserCtxtPtr ctxt;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006050
6051 if (cur == NULL) return(NULL);
6052
Daniel Veillardd692aa41999-02-28 21:54:31 +00006053
6054 ctxt = xmlCreateDocParserCtxt(cur);
6055 if (ctxt == NULL) return(NULL);
Daniel Veillard27d88741999-05-29 11:51:49 +00006056 if (sax != NULL) {
6057 ctxt->sax = sax;
6058 ctxt->userData = NULL;
6059 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006060
6061 xmlParseDocument(ctxt);
Daniel Veillard517752b1999-04-05 12:20:10 +00006062 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006063 else {
6064 ret = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00006065 xmlFreeDoc(ctxt->myDoc);
6066 ctxt->myDoc = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006067 }
Daniel Veillard97fea181999-06-26 23:07:37 +00006068 if (sax != NULL)
6069 ctxt->sax = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006070 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006071
6072 return(ret);
6073}
6074
Daniel Veillard11e00581998-10-24 18:27:49 +00006075/**
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006076 * xmlParseDoc :
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006077 * @cur: a pointer to an array of xmlChar
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006078 *
6079 * parse an XML in-memory document and build a tree.
6080 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006081 * Returns the resulting document tree
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006082 */
6083
Daniel Veillard1e346af1999-02-22 10:33:01 +00006084xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006085xmlParseDoc(xmlChar *cur) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006086 return(xmlSAXParseDoc(NULL, cur, 0));
6087}
6088
6089/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00006090 * xmlSAXParseDTD :
6091 * @sax: the SAX handler block
6092 * @ExternalID: a NAME* containing the External ID of the DTD
6093 * @SystemID: a NAME* containing the URL to the DTD
6094 *
6095 * Load and parse an external subset.
6096 *
6097 * Returns the resulting xmlDtdPtr or NULL in case of error.
6098 */
6099
6100xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006101xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
6102 const xmlChar *SystemID) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00006103 xmlDtdPtr ret = NULL;
6104 xmlParserCtxtPtr ctxt;
Daniel Veillard14fff061999-06-22 21:49:07 +00006105 xmlParserInputPtr input = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00006106 xmlCharEncoding enc;
6107
6108 if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
6109
Daniel Veillardb05deb71999-08-10 19:04:08 +00006110 ctxt = xmlNewParserCtxt();
Daniel Veillard011b63c1999-06-02 17:44:04 +00006111 if (ctxt == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00006112 return(NULL);
6113 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00006114
6115 /*
6116 * Set-up the SAX context
6117 */
6118 if (ctxt == NULL) return(NULL);
6119 if (sax != NULL) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006120 if (ctxt->sax != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00006121 xmlFree(ctxt->sax);
Daniel Veillard011b63c1999-06-02 17:44:04 +00006122 ctxt->sax = sax;
6123 ctxt->userData = NULL;
6124 }
6125
6126 /*
6127 * Ask the Entity resolver to load the damn thing
6128 */
6129
6130 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
6131 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
6132 if (input == NULL) {
Daniel Veillard97fea181999-06-26 23:07:37 +00006133 if (sax != NULL) ctxt->sax = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00006134 xmlFreeParserCtxt(ctxt);
6135 return(NULL);
6136 }
6137
6138 /*
6139 * plug some encoding conversion routines here. !!!
6140 */
6141 xmlPushInput(ctxt, input);
6142 enc = xmlDetectCharEncoding(ctxt->input->cur);
6143 xmlSwitchEncoding(ctxt, enc);
6144
Daniel Veillardb05deb71999-08-10 19:04:08 +00006145 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +00006146 input->filename = (char *) xmlStrdup(SystemID); /* !!!!!!! */
Daniel Veillard011b63c1999-06-02 17:44:04 +00006147 input->line = 1;
6148 input->col = 1;
6149 input->base = ctxt->input->cur;
6150 input->cur = ctxt->input->cur;
6151 input->free = NULL;
6152
6153 /*
6154 * let's parse that entity knowing it's an external subset.
6155 */
6156 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
6157
6158 if (ctxt->myDoc != NULL) {
6159 if (ctxt->wellFormed) {
6160 ret = ctxt->myDoc->intSubset;
6161 ctxt->myDoc->intSubset = NULL;
6162 } else {
6163 ret = NULL;
6164 }
6165 xmlFreeDoc(ctxt->myDoc);
6166 ctxt->myDoc = NULL;
6167 }
Daniel Veillard97fea181999-06-26 23:07:37 +00006168 if (sax != NULL) ctxt->sax = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00006169 xmlFreeParserCtxt(ctxt);
6170
6171 return(ret);
6172}
6173
6174/**
6175 * xmlParseDTD :
6176 * @ExternalID: a NAME* containing the External ID of the DTD
6177 * @SystemID: a NAME* containing the URL to the DTD
6178 *
6179 * Load and parse an external subset.
6180 *
6181 * Returns the resulting xmlDtdPtr or NULL in case of error.
6182 */
6183
6184xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006185xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00006186 return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
6187}
6188
6189/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006190 * xmlRecoverDoc :
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006191 * @cur: a pointer to an array of xmlChar
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006192 *
6193 * parse an XML in-memory document and build a tree.
6194 * In the case the document is not Well Formed, a tree is built anyway
6195 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006196 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006197 */
6198
Daniel Veillard1e346af1999-02-22 10:33:01 +00006199xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006200xmlRecoverDoc(xmlChar *cur) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006201 return(xmlSAXParseDoc(NULL, cur, 1));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006202}
6203
6204/**
Daniel Veillardd692aa41999-02-28 21:54:31 +00006205 * xmlCreateFileParserCtxt :
Daniel Veillard11e00581998-10-24 18:27:49 +00006206 * @filename: the filename
6207 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00006208 * Create a parser context for a file content.
6209 * Automatic support for ZLIB/Compress compressed document is provided
6210 * by default if found at compile-time.
Daniel Veillard11e00581998-10-24 18:27:49 +00006211 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00006212 * Returns the new parser context or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006213 */
Daniel Veillardd692aa41999-02-28 21:54:31 +00006214xmlParserCtxtPtr
6215xmlCreateFileParserCtxt(const char *filename)
6216{
6217 xmlParserCtxtPtr ctxt;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006218 xmlParserInputPtr inputStream;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006219 xmlParserInputBufferPtr buf;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006220 char *directory = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006221
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006222 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
6223 if (buf == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006224
Daniel Veillardb05deb71999-08-10 19:04:08 +00006225 ctxt = xmlNewParserCtxt();
Daniel Veillard260a68f1998-08-13 03:39:55 +00006226 if (ctxt == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006227 return(NULL);
6228 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00006229
6230 inputStream = xmlNewInputStream(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006231 if (inputStream == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00006232 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006233 return(NULL);
6234 }
6235
Daniel Veillard6454aec1999-09-02 22:04:43 +00006236 inputStream->filename = xmlMemStrdup(filename);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006237 inputStream->buf = buf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006238 inputStream->base = inputStream->buf->buffer->content;
6239 inputStream->cur = inputStream->buf->buffer->content;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006240
6241 inputPush(ctxt, inputStream);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006242 if ((ctxt->directory == NULL) && (directory == NULL))
6243 directory = xmlParserGetDirectory(filename);
6244 if ((ctxt->directory == NULL) && (directory != NULL))
6245 ctxt->directory = directory;
6246
Daniel Veillardd692aa41999-02-28 21:54:31 +00006247 return(ctxt);
6248}
6249
6250/**
6251 * xmlSAXParseFile :
6252 * @sax: the SAX handler block
6253 * @filename: the filename
6254 * @recovery: work in recovery mode, i.e. tries to read no Well Formed
6255 * documents
6256 *
6257 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6258 * compressed document is provided by default if found at compile-time.
6259 * It use the given SAX function block to handle the parsing callback.
6260 * If sax is NULL, fallback to the default DOM tree building routines.
6261 *
6262 * Returns the resulting document tree
6263 */
6264
Daniel Veillard011b63c1999-06-02 17:44:04 +00006265xmlDocPtr
6266xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
Daniel Veillardd692aa41999-02-28 21:54:31 +00006267 int recovery) {
6268 xmlDocPtr ret;
6269 xmlParserCtxtPtr ctxt;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006270 char *directory = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006271
6272 ctxt = xmlCreateFileParserCtxt(filename);
6273 if (ctxt == NULL) return(NULL);
Daniel Veillard27d88741999-05-29 11:51:49 +00006274 if (sax != NULL) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006275 if (ctxt->sax != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00006276 xmlFree(ctxt->sax);
Daniel Veillard27d88741999-05-29 11:51:49 +00006277 ctxt->sax = sax;
6278 ctxt->userData = NULL;
6279 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006280
Daniel Veillardb05deb71999-08-10 19:04:08 +00006281 if ((ctxt->directory == NULL) && (directory == NULL))
6282 directory = xmlParserGetDirectory(filename);
6283 if ((ctxt->directory == NULL) && (directory != NULL))
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006284 ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); /* !!!!!!! */
Daniel Veillardb05deb71999-08-10 19:04:08 +00006285
Daniel Veillard260a68f1998-08-13 03:39:55 +00006286 xmlParseDocument(ctxt);
6287
Daniel Veillard517752b1999-04-05 12:20:10 +00006288 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006289 else {
6290 ret = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00006291 xmlFreeDoc(ctxt->myDoc);
6292 ctxt->myDoc = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006293 }
Daniel Veillard97fea181999-06-26 23:07:37 +00006294 if (sax != NULL)
6295 ctxt->sax = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006296 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006297
6298 return(ret);
6299}
6300
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006301/**
6302 * xmlParseFile :
6303 * @filename: the filename
6304 *
6305 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6306 * compressed document is provided by default if found at compile-time.
6307 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006308 * Returns the resulting document tree
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006309 */
6310
Daniel Veillard011b63c1999-06-02 17:44:04 +00006311xmlDocPtr
6312xmlParseFile(const char *filename) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006313 return(xmlSAXParseFile(NULL, filename, 0));
6314}
6315
6316/**
6317 * xmlRecoverFile :
6318 * @filename: the filename
6319 *
6320 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6321 * compressed document is provided by default if found at compile-time.
6322 * In the case the document is not Well Formed, a tree is built anyway
6323 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006324 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006325 */
6326
Daniel Veillard011b63c1999-06-02 17:44:04 +00006327xmlDocPtr
6328xmlRecoverFile(const char *filename) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006329 return(xmlSAXParseFile(NULL, filename, 1));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006330}
Daniel Veillard260a68f1998-08-13 03:39:55 +00006331
Daniel Veillard11e00581998-10-24 18:27:49 +00006332/**
Daniel Veillardd692aa41999-02-28 21:54:31 +00006333 * xmlCreateMemoryParserCtxt :
Daniel Veillard1e346af1999-02-22 10:33:01 +00006334 * @buffer: an pointer to a char array
Daniel Veillard11e00581998-10-24 18:27:49 +00006335 * @size: the siwe of the array
6336 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00006337 * Create a parser context for an XML in-memory document.
Daniel Veillard11e00581998-10-24 18:27:49 +00006338 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00006339 * Returns the new parser context or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006340 */
Daniel Veillardd692aa41999-02-28 21:54:31 +00006341xmlParserCtxtPtr
6342xmlCreateMemoryParserCtxt(char *buffer, int size) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006343 xmlParserCtxtPtr ctxt;
6344 xmlParserInputPtr input;
Daniel Veillard27d88741999-05-29 11:51:49 +00006345 xmlCharEncoding enc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006346
6347 buffer[size - 1] = '\0';
6348
Daniel Veillardb05deb71999-08-10 19:04:08 +00006349 ctxt = xmlNewParserCtxt();
Daniel Veillard260a68f1998-08-13 03:39:55 +00006350 if (ctxt == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006351 return(NULL);
6352 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00006353
6354 input = xmlNewInputStream(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006355 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00006356 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006357 return(NULL);
6358 }
6359
6360 input->filename = NULL;
6361 input->line = 1;
6362 input->col = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006363 input->buf = NULL;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006364 input->consumed = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006365
6366 /*
Daniel Veillard27d88741999-05-29 11:51:49 +00006367 * plug some encoding conversion routines here. !!!
Daniel Veillard260a68f1998-08-13 03:39:55 +00006368 */
Daniel Veillardb96e6431999-08-29 21:02:19 +00006369 enc = xmlDetectCharEncoding(BAD_CAST buffer);
Daniel Veillard27d88741999-05-29 11:51:49 +00006370 xmlSwitchEncoding(ctxt, enc);
6371
Daniel Veillardb96e6431999-08-29 21:02:19 +00006372 input->base = BAD_CAST buffer;
6373 input->cur = BAD_CAST buffer;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006374 input->free = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006375
6376 inputPush(ctxt, input);
Daniel Veillardd692aa41999-02-28 21:54:31 +00006377 return(ctxt);
6378}
6379
6380/**
6381 * xmlSAXParseMemory :
6382 * @sax: the SAX handler block
6383 * @buffer: an pointer to a char array
6384 * @size: the siwe of the array
6385 * @recovery: work in recovery mode, i.e. tries to read no Well Formed
6386 * documents
6387 *
6388 * parse an XML in-memory block and use the given SAX function block
6389 * to handle the parsing callback. If sax is NULL, fallback to the default
6390 * DOM tree building routines.
6391 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00006392 * Returns the resulting document tree
6393 */
6394xmlDocPtr
6395xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
6396 xmlDocPtr ret;
6397 xmlParserCtxtPtr ctxt;
6398
6399 ctxt = xmlCreateMemoryParserCtxt(buffer, size);
6400 if (ctxt == NULL) return(NULL);
Daniel Veillard27d88741999-05-29 11:51:49 +00006401 if (sax != NULL) {
6402 ctxt->sax = sax;
6403 ctxt->userData = NULL;
6404 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006405
6406 xmlParseDocument(ctxt);
6407
Daniel Veillard517752b1999-04-05 12:20:10 +00006408 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006409 else {
6410 ret = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00006411 xmlFreeDoc(ctxt->myDoc);
6412 ctxt->myDoc = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006413 }
Daniel Veillard97fea181999-06-26 23:07:37 +00006414 if (sax != NULL)
6415 ctxt->sax = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00006416 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006417
6418 return(ret);
6419}
6420
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006421/**
6422 * xmlParseMemory :
Daniel Veillard1e346af1999-02-22 10:33:01 +00006423 * @buffer: an pointer to a char array
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006424 * @size: the size of the array
6425 *
6426 * parse an XML in-memory block and build a tree.
6427 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006428 * Returns the resulting document tree
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006429 */
6430
6431xmlDocPtr xmlParseMemory(char *buffer, int size) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006432 return(xmlSAXParseMemory(NULL, buffer, size, 0));
6433}
6434
6435/**
6436 * xmlRecoverMemory :
Daniel Veillard1e346af1999-02-22 10:33:01 +00006437 * @buffer: an pointer to a char array
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006438 * @size: the size of the array
6439 *
6440 * parse an XML in-memory block and build a tree.
6441 * In the case the document is not Well Formed, a tree is built anyway
6442 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006443 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006444 */
6445
6446xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
6447 return(xmlSAXParseMemory(NULL, buffer, size, 1));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00006448}
Daniel Veillard260a68f1998-08-13 03:39:55 +00006449
Daniel Veillard260a68f1998-08-13 03:39:55 +00006450
Daniel Veillard11e00581998-10-24 18:27:49 +00006451/**
6452 * xmlSetupParserForBuffer:
6453 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006454 * @buffer: a xmlChar * buffer
Daniel Veillard11e00581998-10-24 18:27:49 +00006455 * @filename: a file name
6456 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00006457 * Setup the parser context to parse a new buffer; Clears any prior
6458 * contents from the parser context. The buffer parameter must not be
6459 * NULL, but the filename parameter can be
6460 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006461void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006462xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
Daniel Veillard260a68f1998-08-13 03:39:55 +00006463 const char* filename)
6464{
Daniel Veillardb05deb71999-08-10 19:04:08 +00006465 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006466
Daniel Veillardb05deb71999-08-10 19:04:08 +00006467 input = xmlNewInputStream(ctxt);
6468 if (input == NULL) {
6469 perror("malloc");
Daniel Veillard6454aec1999-09-02 22:04:43 +00006470 xmlFree(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006471 exit(1);
6472 }
6473
6474 xmlClearParserCtxt(ctxt);
6475 if (filename != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00006476 input->filename = xmlMemStrdup(filename);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006477 input->base = buffer;
6478 input->cur = buffer;
6479 inputPush(ctxt, input);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006480}
6481
Daniel Veillard7a66ee61999-09-26 11:31:02 +00006482/**
6483 * xmlSAXUserParseFile:
6484 * @sax: a SAX handler
6485 * @user_data: The user data returned on SAX callbacks
6486 * @filename: a file name
6487 *
6488 * parse an XML file and call the given SAX handler routines.
6489 * Automatic support for ZLIB/Compress compressed document is provided
6490 *
6491 * Returns 0 in case of success or a error number otherwise
6492 */
6493int xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
6494 const char *filename) {
6495 int ret = 0;
6496 xmlParserCtxtPtr ctxt;
6497
6498 ctxt = xmlCreateFileParserCtxt(filename);
6499 if (ctxt == NULL) return -1;
6500 ctxt->sax = sax;
6501 ctxt->userData = user_data;
6502
6503 xmlParseDocument(ctxt);
6504
6505 if (ctxt->wellFormed)
6506 ret = 0;
6507 else {
6508 if (ctxt->errNo != 0)
6509 ret = ctxt->errNo;
6510 else
6511 ret = -1;
6512 }
6513 if (sax != NULL)
6514 ctxt->sax = NULL;
6515 xmlFreeParserCtxt(ctxt);
6516
6517 return ret;
6518}
6519
6520/**
6521 * xmlSAXUserParseMemory:
6522 * @sax: a SAX handler
6523 * @user_data: The user data returned on SAX callbacks
6524 * @buffer: an in-memory XML document input
6525 * @size: the lenght of the XML document in bytes
6526 *
6527 * A better SAX parsing routine.
6528 * parse an XML in-memory buffer and call the given SAX handler routines.
6529 *
6530 * Returns 0 in case of success or a error number otherwise
6531 */
6532int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
6533 char *buffer, int size) {
6534 int ret = 0;
6535 xmlParserCtxtPtr ctxt;
6536
6537 ctxt = xmlCreateMemoryParserCtxt(buffer, size);
6538 if (ctxt == NULL) return -1;
6539 ctxt->sax = sax;
6540 ctxt->userData = user_data;
6541
6542 xmlParseDocument(ctxt);
6543
6544 if (ctxt->wellFormed)
6545 ret = 0;
6546 else {
6547 if (ctxt->errNo != 0)
6548 ret = ctxt->errNo;
6549 else
6550 ret = -1;
6551 }
6552 if (sax != NULL)
6553 ctxt->sax = NULL;
6554 xmlFreeParserCtxt(ctxt);
6555
6556 return ret;
6557}
6558
Daniel Veillard260a68f1998-08-13 03:39:55 +00006559
Daniel Veillardb05deb71999-08-10 19:04:08 +00006560/************************************************************************
6561 * *
6562 * Miscelaneous *
6563 * *
6564 ************************************************************************/
6565
6566
Daniel Veillard11e00581998-10-24 18:27:49 +00006567/**
6568 * xmlParserFindNodeInfo:
6569 * @ctxt: an XML parser context
6570 * @node: an XML node within the tree
6571 *
6572 * Find the parser node info struct for a given node
6573 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006574 * Returns an xmlParserNodeInfo block pointer or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006575 */
6576const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
6577 const xmlNode* node)
6578{
6579 unsigned long pos;
6580
6581 /* Find position where node should be at */
6582 pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
6583 if ( ctx->node_seq.buffer[pos].node == node )
6584 return &ctx->node_seq.buffer[pos];
6585 else
6586 return NULL;
6587}
6588
6589
Daniel Veillard11e00581998-10-24 18:27:49 +00006590/**
6591 * xmlInitNodeInfoSeq :
6592 * @seq: a node info sequence pointer
6593 *
6594 * -- Initialize (set to initial state) node info sequence
Daniel Veillard260a68f1998-08-13 03:39:55 +00006595 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006596void
6597xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
Daniel Veillard260a68f1998-08-13 03:39:55 +00006598{
6599 seq->length = 0;
6600 seq->maximum = 0;
6601 seq->buffer = NULL;
6602}
6603
Daniel Veillard11e00581998-10-24 18:27:49 +00006604/**
6605 * xmlClearNodeInfoSeq :
6606 * @seq: a node info sequence pointer
6607 *
6608 * -- Clear (release memory and reinitialize) node
Daniel Veillard260a68f1998-08-13 03:39:55 +00006609 * info sequence
6610 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006611void
6612xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
Daniel Veillard260a68f1998-08-13 03:39:55 +00006613{
6614 if ( seq->buffer != NULL )
Daniel Veillard6454aec1999-09-02 22:04:43 +00006615 xmlFree(seq->buffer);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006616 xmlInitNodeInfoSeq(seq);
6617}
6618
6619
Daniel Veillard11e00581998-10-24 18:27:49 +00006620/**
6621 * xmlParserFindNodeInfoIndex:
6622 * @seq: a node info sequence pointer
6623 * @node: an XML node pointer
6624 *
6625 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00006626 * xmlParserFindNodeInfoIndex : Find the index that the info record for
6627 * the given node is or should be at in a sorted sequence
Daniel Veillard1164e751999-02-16 16:29:17 +00006628 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006629 * Returns a long indicating the position of the record
Daniel Veillard260a68f1998-08-13 03:39:55 +00006630 */
6631unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
6632 const xmlNode* node)
6633{
6634 unsigned long upper, lower, middle;
6635 int found = 0;
6636
6637 /* Do a binary search for the key */
6638 lower = 1;
6639 upper = seq->length;
6640 middle = 0;
6641 while ( lower <= upper && !found) {
6642 middle = lower + (upper - lower) / 2;
6643 if ( node == seq->buffer[middle - 1].node )
6644 found = 1;
6645 else if ( node < seq->buffer[middle - 1].node )
6646 upper = middle - 1;
6647 else
6648 lower = middle + 1;
6649 }
6650
6651 /* Return position */
6652 if ( middle == 0 || seq->buffer[middle - 1].node < node )
6653 return middle;
6654 else
6655 return middle - 1;
6656}
6657
6658
Daniel Veillard11e00581998-10-24 18:27:49 +00006659/**
6660 * xmlParserAddNodeInfo:
6661 * @ctxt: an XML parser context
Daniel Veillard1e346af1999-02-22 10:33:01 +00006662 * @info: a node info sequence pointer
Daniel Veillard11e00581998-10-24 18:27:49 +00006663 *
6664 * Insert node info record into the sorted sequence
Daniel Veillard260a68f1998-08-13 03:39:55 +00006665 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006666void
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006667xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
Daniel Veillard1e346af1999-02-22 10:33:01 +00006668 const xmlParserNodeInfo* info)
Daniel Veillard260a68f1998-08-13 03:39:55 +00006669{
6670 unsigned long pos;
6671 static unsigned int block_size = 5;
6672
6673 /* Find pos and check to see if node is already in the sequence */
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006674 pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
6675 if ( pos < ctxt->node_seq.length
6676 && ctxt->node_seq.buffer[pos].node == info->node ) {
6677 ctxt->node_seq.buffer[pos] = *info;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006678 }
6679
6680 /* Otherwise, we need to add new node to buffer */
6681 else {
6682 /* Expand buffer by 5 if needed */
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006683 if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006684 xmlParserNodeInfo* tmp_buffer;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006685 unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
6686 *(ctxt->node_seq.maximum + block_size));
Daniel Veillard260a68f1998-08-13 03:39:55 +00006687
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006688 if ( ctxt->node_seq.buffer == NULL )
Daniel Veillard6454aec1999-09-02 22:04:43 +00006689 tmp_buffer = (xmlParserNodeInfo*) xmlMalloc(byte_size);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006690 else
Daniel Veillard6454aec1999-09-02 22:04:43 +00006691 tmp_buffer = (xmlParserNodeInfo*) xmlRealloc(ctxt->node_seq.buffer, byte_size);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006692
6693 if ( tmp_buffer == NULL ) {
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006694 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006695 ctxt->sax->error(ctxt->userData, "Out of memory\n");
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006696 ctxt->errNo = XML_ERR_NO_MEMORY;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006697 return;
6698 }
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006699 ctxt->node_seq.buffer = tmp_buffer;
6700 ctxt->node_seq.maximum += block_size;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006701 }
6702
6703 /* If position is not at end, move elements out of the way */
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006704 if ( pos != ctxt->node_seq.length ) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006705 unsigned long i;
6706
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006707 for ( i = ctxt->node_seq.length; i > pos; i-- )
6708 ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
Daniel Veillard260a68f1998-08-13 03:39:55 +00006709 }
6710
6711 /* Copy element and increase length */
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006712 ctxt->node_seq.buffer[pos] = *info;
6713 ctxt->node_seq.length++;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006714 }
6715}
Daniel Veillard011b63c1999-06-02 17:44:04 +00006716
6717
Daniel Veillardb05deb71999-08-10 19:04:08 +00006718/**
6719 * xmlSubstituteEntitiesDefault :
6720 * @val: int 0 or 1
6721 *
6722 * Set and return the previous value for default entity support.
6723 * Initially the parser always keep entity references instead of substituting
6724 * entity values in the output. This function has to be used to change the
6725 * default parser behaviour
6726 * SAX::subtituteEntities() has to be used for changing that on a file by
6727 * file basis.
6728 *
6729 * Returns the last value for 0 for no substitution, 1 for substitution.
6730 */
6731
6732int
6733xmlSubstituteEntitiesDefault(int val) {
6734 int old = xmlSubstituteEntitiesDefaultValue;
6735
6736 xmlSubstituteEntitiesDefaultValue = val;
6737 return(old);
6738}
6739