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