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