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