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