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