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