Annotation of XML/parser.c, revision 1.170
1.1 veillard 1: /*
1.3 veillard 2: * parser.c : an XML 1.0 non-verifying parser
1.15 veillard 3: *
4: * See Copyright for the status of this software.
5: *
1.60 daniel 6: * Daniel.Veillard@w3.org
1.1 veillard 7: */
8:
1.26 daniel 9: #ifdef WIN32
1.138 daniel 10: #include "win32config.h"
1.26 daniel 11: #else
1.121 daniel 12: #include "config.h"
1.26 daniel 13: #endif
1.121 daniel 14:
1.1 veillard 15: #include <stdio.h>
1.121 daniel 16: #include <string.h> /* for memset() only */
17: #ifdef HAVE_CTYPE_H
1.1 veillard 18: #include <ctype.h>
1.121 daniel 19: #endif
20: #ifdef HAVE_STDLIB_H
1.50 daniel 21: #include <stdlib.h>
1.121 daniel 22: #endif
23: #ifdef HAVE_SYS_STAT_H
1.9 httpng 24: #include <sys/stat.h>
1.121 daniel 25: #endif
1.9 httpng 26: #ifdef HAVE_FCNTL_H
27: #include <fcntl.h>
28: #endif
1.10 httpng 29: #ifdef HAVE_UNISTD_H
30: #include <unistd.h>
31: #endif
1.20 daniel 32: #ifdef HAVE_ZLIB_H
33: #include <zlib.h>
34: #endif
1.1 veillard 35:
1.119 daniel 36: #include "xmlmemory.h"
1.14 veillard 37: #include "tree.h"
1.1 veillard 38: #include "parser.h"
1.14 veillard 39: #include "entities.h"
1.75 daniel 40: #include "encoding.h"
1.61 daniel 41: #include "valid.h"
1.69 daniel 42: #include "parserInternals.h"
1.91 daniel 43: #include "xmlIO.h"
1.122 daniel 44: #include "xml-error.h"
1.1 veillard 45:
1.140 daniel 46: #define XML_PARSER_BIG_BUFFER_SIZE 1000
47: #define XML_PARSER_BUFFER_SIZE 100
48:
1.86 daniel 49: const char *xmlParserVersion = LIBXML_VERSION;
1.160 daniel 50: int xmlGetWarningsDefaultValue = 1;
1.86 daniel 51:
1.139 daniel 52: /*
53: * List of XML prefixed PI allowed by W3C specs
54: */
55:
56: const char *xmlW3CPIs[] = {
57: "xml-stylesheet",
58: NULL
59: };
1.91 daniel 60:
1.151 daniel 61: void xmlParserHandleReference(xmlParserCtxtPtr ctxt);
62: void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
63: xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
64: const xmlChar **str);
1.91 daniel 65: /************************************************************************
66: * *
67: * Input handling functions for progressive parsing *
68: * *
69: ************************************************************************/
70:
71: /* #define DEBUG_INPUT */
1.140 daniel 72: /* #define DEBUG_STACK */
73: /* #define DEBUG_PUSH */
74:
1.91 daniel 75:
1.110 daniel 76: #define INPUT_CHUNK 250
77: /* we need to keep enough input to show errors in context */
78: #define LINE_LEN 80
1.91 daniel 79:
80: #ifdef DEBUG_INPUT
81: #define CHECK_BUFFER(in) check_buffer(in)
82:
83: void check_buffer(xmlParserInputPtr in) {
84: if (in->base != in->buf->buffer->content) {
85: fprintf(stderr, "xmlParserInput: base mismatch problem\n");
86: }
87: if (in->cur < in->base) {
88: fprintf(stderr, "xmlParserInput: cur < base problem\n");
89: }
90: if (in->cur > in->base + in->buf->buffer->use) {
91: fprintf(stderr, "xmlParserInput: cur > base + use problem\n");
92: }
93: fprintf(stderr,"buffer %x : content %x, cur %d, use %d, size %d\n",
94: (int) in, (int) in->buf->buffer->content, in->cur - in->base,
95: in->buf->buffer->use, in->buf->buffer->size);
96: }
97:
1.110 daniel 98: #else
99: #define CHECK_BUFFER(in)
100: #endif
101:
1.91 daniel 102:
103: /**
104: * xmlParserInputRead:
105: * @in: an XML parser input
106: * @len: an indicative size for the lookahead
107: *
108: * This function refresh the input for the parser. It doesn't try to
109: * preserve pointers to the input buffer, and discard already read data
110: *
1.123 daniel 111: * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91 daniel 112: * end of this entity
113: */
114: int
115: xmlParserInputRead(xmlParserInputPtr in, int len) {
116: int ret;
117: int used;
118: int index;
119:
120: #ifdef DEBUG_INPUT
121: fprintf(stderr, "Read\n");
122: #endif
123: if (in->buf == NULL) return(-1);
124: if (in->base == NULL) return(-1);
125: if (in->cur == NULL) return(-1);
126: if (in->buf->buffer == NULL) return(-1);
127:
128: CHECK_BUFFER(in);
129:
130: used = in->cur - in->buf->buffer->content;
131: ret = xmlBufferShrink(in->buf->buffer, used);
132: if (ret > 0) {
133: in->cur -= ret;
134: in->consumed += ret;
135: }
136: ret = xmlParserInputBufferRead(in->buf, len);
137: if (in->base != in->buf->buffer->content) {
138: /*
139: * the buffer has been realloced
140: */
141: index = in->cur - in->base;
142: in->base = in->buf->buffer->content;
143: in->cur = &in->buf->buffer->content[index];
144: }
145:
146: CHECK_BUFFER(in);
147:
148: return(ret);
149: }
150:
151: /**
152: * xmlParserInputGrow:
153: * @in: an XML parser input
154: * @len: an indicative size for the lookahead
155: *
156: * This function increase the input for the parser. It tries to
157: * preserve pointers to the input buffer, and keep already read data
158: *
1.123 daniel 159: * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91 daniel 160: * end of this entity
161: */
162: int
163: xmlParserInputGrow(xmlParserInputPtr in, int len) {
164: int ret;
165: int index;
166:
167: #ifdef DEBUG_INPUT
168: fprintf(stderr, "Grow\n");
169: #endif
170: if (in->buf == NULL) return(-1);
171: if (in->base == NULL) return(-1);
172: if (in->cur == NULL) return(-1);
173: if (in->buf->buffer == NULL) return(-1);
174:
175: CHECK_BUFFER(in);
176:
177: index = in->cur - in->base;
178: if (in->buf->buffer->use > index + INPUT_CHUNK) {
179:
180: CHECK_BUFFER(in);
181:
182: return(0);
183: }
1.148 daniel 184: if ((in->buf->httpIO != NULL) || (in->buf->ftpIO != NULL) ||
185: (in->buf->file != NULL) ||
1.140 daniel 186: #ifdef HAVE_ZLIB_H
187: (in->buf->gzfile != NULL) ||
188: #endif
189: (in->buf->fd >= 0))
190: ret = xmlParserInputBufferGrow(in->buf, len);
191: else
192: return(0);
1.135 daniel 193:
194: /*
195: * NOTE : in->base may be a "dandling" i.e. freed pointer in this
196: * block, but we use it really as an integer to do some
197: * pointer arithmetic. Insure will raise it as a bug but in
198: * that specific case, that's not !
199: */
1.91 daniel 200: if (in->base != in->buf->buffer->content) {
201: /*
202: * the buffer has been realloced
203: */
204: index = in->cur - in->base;
205: in->base = in->buf->buffer->content;
206: in->cur = &in->buf->buffer->content[index];
207: }
208:
209: CHECK_BUFFER(in);
210:
211: return(ret);
212: }
213:
214: /**
215: * xmlParserInputShrink:
216: * @in: an XML parser input
217: *
218: * This function removes used input for the parser.
219: */
220: void
221: xmlParserInputShrink(xmlParserInputPtr in) {
222: int used;
223: int ret;
224: int index;
225:
226: #ifdef DEBUG_INPUT
227: fprintf(stderr, "Shrink\n");
228: #endif
229: if (in->buf == NULL) return;
230: if (in->base == NULL) return;
231: if (in->cur == NULL) return;
232: if (in->buf->buffer == NULL) return;
233:
234: CHECK_BUFFER(in);
235:
236: used = in->cur - in->buf->buffer->content;
237: if (used > INPUT_CHUNK) {
1.110 daniel 238: ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
1.91 daniel 239: if (ret > 0) {
240: in->cur -= ret;
241: in->consumed += ret;
242: }
243: }
244:
245: CHECK_BUFFER(in);
246:
247: if (in->buf->buffer->use > INPUT_CHUNK) {
248: return;
249: }
250: xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
251: if (in->base != in->buf->buffer->content) {
252: /*
253: * the buffer has been realloced
254: */
255: index = in->cur - in->base;
256: in->base = in->buf->buffer->content;
257: in->cur = &in->buf->buffer->content[index];
258: }
259:
260: CHECK_BUFFER(in);
261: }
262:
1.45 daniel 263: /************************************************************************
264: * *
265: * Parser stacks related functions and macros *
266: * *
267: ************************************************************************/
1.79 daniel 268:
269: int xmlSubstituteEntitiesDefaultValue = 0;
1.100 daniel 270: int xmlDoValidityCheckingDefaultValue = 0;
1.135 daniel 271: xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
272: const xmlChar ** str);
1.79 daniel 273:
1.1 veillard 274: /*
1.40 daniel 275: * Generic function for accessing stacks in the Parser Context
1.1 veillard 276: */
277:
1.140 daniel 278: #define PUSH_AND_POP(scope, type, name) \
279: scope int name##Push(xmlParserCtxtPtr ctxt, type value) { \
1.31 daniel 280: if (ctxt->name##Nr >= ctxt->name##Max) { \
281: ctxt->name##Max *= 2; \
1.119 daniel 282: ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \
1.40 daniel 283: ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
284: if (ctxt->name##Tab == NULL) { \
1.31 daniel 285: fprintf(stderr, "realloc failed !\n"); \
1.145 daniel 286: return(0); \
1.31 daniel 287: } \
288: } \
1.40 daniel 289: ctxt->name##Tab[ctxt->name##Nr] = value; \
290: ctxt->name = value; \
291: return(ctxt->name##Nr++); \
1.31 daniel 292: } \
1.140 daniel 293: scope type name##Pop(xmlParserCtxtPtr ctxt) { \
1.69 daniel 294: type ret; \
1.40 daniel 295: if (ctxt->name##Nr <= 0) return(0); \
296: ctxt->name##Nr--; \
1.50 daniel 297: if (ctxt->name##Nr > 0) \
298: ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \
299: else \
300: ctxt->name = NULL; \
1.69 daniel 301: ret = ctxt->name##Tab[ctxt->name##Nr]; \
302: ctxt->name##Tab[ctxt->name##Nr] = 0; \
303: return(ret); \
1.31 daniel 304: } \
305:
1.140 daniel 306: PUSH_AND_POP(extern, xmlParserInputPtr, input)
307: PUSH_AND_POP(extern, xmlNodePtr, node)
308: PUSH_AND_POP(extern, xmlChar*, name)
1.40 daniel 309:
1.55 daniel 310: /*
311: * Macros for accessing the content. Those should be used only by the parser,
312: * and not exported.
313: *
314: * Dirty macros, i.e. one need to make assumption on the context to use them
315: *
1.123 daniel 316: * CUR_PTR return the current pointer to the xmlChar to be parsed.
1.151 daniel 317: * To be used with extreme caution since operations consuming
318: * characters may move the input buffer to a different location !
1.123 daniel 319: * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled
1.152 daniel 320: * in ISO-Latin or UTF-8.
1.151 daniel 321: * This should be used internally by the parser
1.55 daniel 322: * only to compare to ASCII values otherwise it would break when
323: * running with UTF-8 encoding.
1.123 daniel 324: * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
1.55 daniel 325: * to compare on ASCII based substring.
1.123 daniel 326: * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1.55 daniel 327: * strings within the parser.
328: *
1.77 daniel 329: * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1.55 daniel 330: *
331: * NEXT Skip to the next character, this does the proper decoding
332: * in UTF-8 mode. It also pop-up unfinished entities on the fly.
1.77 daniel 333: * COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
1.155 daniel 334: * CUR_CHAR Return the current char as an int as well as its lenght.
1.55 daniel 335: */
1.45 daniel 336:
1.152 daniel 337: #define RAW (ctxt->token ? -1 : (*ctxt->input->cur))
1.97 daniel 338: #define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
1.55 daniel 339: #define NXT(val) ctxt->input->cur[(val)]
340: #define CUR_PTR ctxt->input->cur
1.154 daniel 341:
1.164 daniel 342: #define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val); \
343: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
1.168 daniel 344: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); \
345: if ((*ctxt->input->cur == 0) && \
346: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
347: xmlPopInput(ctxt)
1.164 daniel 348:
1.97 daniel 349: #define SHRINK xmlParserInputShrink(ctxt->input); \
350: if ((*ctxt->input->cur == 0) && \
351: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
352: xmlPopInput(ctxt)
353:
354: #define GROW xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
355: if ((*ctxt->input->cur == 0) && \
356: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
357: xmlPopInput(ctxt)
1.55 daniel 358:
1.155 daniel 359: #define SKIP_BLANKS xmlSkipBlankChars(ctxt);
1.154 daniel 360:
1.151 daniel 361: #define NEXT xmlNextChar(ctxt);
1.154 daniel 362:
1.153 daniel 363: #define NEXTL(l) \
364: if (*(ctxt->input->cur) == '\n') { \
365: ctxt->input->line++; ctxt->input->col = 1; \
366: } else ctxt->input->col++; \
1.154 daniel 367: ctxt->token = 0; ctxt->input->cur += l; \
368: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
369: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);
370:
1.152 daniel 371: #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l);
1.162 daniel 372: #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l);
1.154 daniel 373:
1.152 daniel 374: #define COPY_BUF(l,b,i,v) \
375: if (l == 1) b[i++] = (xmlChar) v; \
376: else i += xmlCopyChar(l,&b[i],v);
1.151 daniel 377:
378: /**
379: * xmlNextChar:
380: * @ctxt: the XML parser context
381: *
382: * Skip to the next char input char.
383: */
1.55 daniel 384:
1.151 daniel 385: void
386: xmlNextChar(xmlParserCtxtPtr ctxt) {
387: if (ctxt->token != 0) ctxt->token = 0;
388: else {
389: if ((*ctxt->input->cur == 0) &&
390: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0) &&
391: (ctxt->instate != XML_PARSER_COMMENT)) {
392: /*
393: * If we are at the end of the current entity and
394: * the context allows it, we pop consumed entities
395: * automatically.
396: * TODO: the auto closing should be blocked in other cases
397: */
398: xmlPopInput(ctxt);
399: } else {
400: if (*(ctxt->input->cur) == '\n') {
401: ctxt->input->line++; ctxt->input->col = 1;
402: } else ctxt->input->col++;
403: if (ctxt->encoding == NULL) {
404: /*
405: * We are supposed to handle UTF8, check it's valid
406: * From rfc2044: encoding of the Unicode values on UTF-8:
407: *
408: * UCS-4 range (hex.) UTF-8 octet sequence (binary)
409: * 0000 0000-0000 007F 0xxxxxxx
410: * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
411: * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
412: *
1.160 daniel 413: * Check for the 0x110000 limit too
1.151 daniel 414: */
415: const unsigned char *cur = ctxt->input->cur;
416: unsigned char c;
1.91 daniel 417:
1.151 daniel 418: c = *cur;
419: if (c & 0x80) {
420: if (cur[1] == 0)
421: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
422: if ((cur[1] & 0xc0) != 0x80)
423: goto encoding_error;
424: if ((c & 0xe0) == 0xe0) {
425: unsigned int val;
426:
427: if (cur[2] == 0)
428: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
429: if ((cur[2] & 0xc0) != 0x80)
430: goto encoding_error;
431: if ((c & 0xf0) == 0xf0) {
432: if (cur[3] == 0)
433: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
434: if (((c & 0xf8) != 0xf0) ||
435: ((cur[3] & 0xc0) != 0x80))
436: goto encoding_error;
437: /* 4-byte code */
438: ctxt->input->cur += 4;
439: val = (cur[0] & 0x7) << 18;
440: val |= (cur[1] & 0x3f) << 12;
441: val |= (cur[2] & 0x3f) << 6;
442: val |= cur[3] & 0x3f;
443: } else {
444: /* 3-byte code */
445: ctxt->input->cur += 3;
446: val = (cur[0] & 0xf) << 12;
447: val |= (cur[1] & 0x3f) << 6;
448: val |= cur[2] & 0x3f;
449: }
450: if (((val > 0xd7ff) && (val < 0xe000)) ||
451: ((val > 0xfffd) && (val < 0x10000)) ||
1.160 daniel 452: (val >= 0x110000)) {
1.151 daniel 453: if ((ctxt->sax != NULL) &&
454: (ctxt->sax->error != NULL))
455: ctxt->sax->error(ctxt->userData,
456: "Char out of allowed range\n");
457: ctxt->errNo = XML_ERR_INVALID_ENCODING;
458: ctxt->wellFormed = 0;
459: }
460: } else
461: /* 2-byte code */
462: ctxt->input->cur += 2;
463: } else
464: /* 1-byte code */
465: ctxt->input->cur++;
466: } else {
467: /*
468: * Assume it's a fixed lenght encoding (1) with
469: * a compatibke encoding for the ASCII set, since
470: * XML constructs only use < 128 chars
471: */
472: ctxt->input->cur++;
473: }
474: ctxt->nbChars++;
475: if (*ctxt->input->cur == 0)
476: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
477: }
478: }
1.154 daniel 479: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
480: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);
1.168 daniel 481: if ((*ctxt->input->cur == 0) &&
482: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
483: xmlPopInput(ctxt);
1.151 daniel 484: return;
485: encoding_error:
486: /*
487: * If we detect an UTF8 error that probably mean that the
488: * input encoding didn't get properly advertized in the
489: * declaration header. Report the error and switch the encoding
490: * to ISO-Latin-1 (if you don't like this policy, just declare the
491: * encoding !)
492: */
493: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
494: ctxt->sax->error(ctxt->userData,
495: "Input is not proper UTF-8, indicate encoding !\n");
496: ctxt->errNo = XML_ERR_INVALID_ENCODING;
497:
498: ctxt->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
499: ctxt->input->cur++;
500: return;
501: }
1.42 daniel 502:
1.152 daniel 503: /**
504: * xmlCurrentChar:
505: * @ctxt: the XML parser context
506: * @len: pointer to the length of the char read
507: *
508: * The current char value, if using UTF-8 this may actaully span multiple
509: * bytes in the input buffer.
510: *
511: * Returns the current char value and its lenght
512: */
513:
514: int
515: xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
516: if (ctxt->token != 0) {
517: *len = 0;
518: return(ctxt->token);
519: }
520: if (ctxt->encoding == NULL) {
521: /*
522: * We are supposed to handle UTF8, check it's valid
523: * From rfc2044: encoding of the Unicode values on UTF-8:
524: *
525: * UCS-4 range (hex.) UTF-8 octet sequence (binary)
526: * 0000 0000-0000 007F 0xxxxxxx
527: * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
528: * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
529: *
1.160 daniel 530: * Check for the 0x110000 limit too
1.152 daniel 531: */
532: const unsigned char *cur = ctxt->input->cur;
533: unsigned char c;
534: unsigned int val;
535:
536: c = *cur;
537: if (c & 0x80) {
538: if (cur[1] == 0)
539: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
540: if ((cur[1] & 0xc0) != 0x80)
541: goto encoding_error;
542: if ((c & 0xe0) == 0xe0) {
543:
544: if (cur[2] == 0)
545: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
546: if ((cur[2] & 0xc0) != 0x80)
547: goto encoding_error;
548: if ((c & 0xf0) == 0xf0) {
549: if (cur[3] == 0)
550: xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
551: if (((c & 0xf8) != 0xf0) ||
552: ((cur[3] & 0xc0) != 0x80))
553: goto encoding_error;
554: /* 4-byte code */
555: *len = 4;
556: val = (cur[0] & 0x7) << 18;
557: val |= (cur[1] & 0x3f) << 12;
558: val |= (cur[2] & 0x3f) << 6;
559: val |= cur[3] & 0x3f;
560: } else {
561: /* 3-byte code */
562: *len = 3;
563: val = (cur[0] & 0xf) << 12;
564: val |= (cur[1] & 0x3f) << 6;
565: val |= cur[2] & 0x3f;
566: }
567: } else {
568: /* 2-byte code */
569: *len = 2;
570: val = (cur[0] & 0x1f) << 6;
1.168 daniel 571: val |= cur[1] & 0x3f;
1.152 daniel 572: }
573: if (!IS_CHAR(val)) {
574: if ((ctxt->sax != NULL) &&
575: (ctxt->sax->error != NULL))
576: ctxt->sax->error(ctxt->userData,
577: "Char out of allowed range\n");
578: ctxt->errNo = XML_ERR_INVALID_ENCODING;
579: ctxt->wellFormed = 0;
580: }
581: return(val);
582: } else {
583: /* 1-byte code */
584: *len = 1;
585: return((int) *ctxt->input->cur);
586: }
587: }
588: /*
589: * Assume it's a fixed lenght encoding (1) with
590: * a compatibke encoding for the ASCII set, since
591: * XML constructs only use < 128 chars
592: */
593: *len = 1;
594: return((int) *ctxt->input->cur);
595: encoding_error:
596: /*
597: * If we detect an UTF8 error that probably mean that the
598: * input encoding didn't get properly advertized in the
599: * declaration header. Report the error and switch the encoding
600: * to ISO-Latin-1 (if you don't like this policy, just declare the
601: * encoding !)
602: */
603: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
604: ctxt->sax->error(ctxt->userData,
605: "Input is not proper UTF-8, indicate encoding !\n");
606: ctxt->errNo = XML_ERR_INVALID_ENCODING;
607:
608: ctxt->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
609: *len = 1;
610: return((int) *ctxt->input->cur);
611: }
612:
613: /**
1.162 daniel 614: * xmlStringCurrentChar:
615: * @ctxt: the XML parser context
616: * @cur: pointer to the beginning of the char
617: * @len: pointer to the length of the char read
618: *
619: * The current char value, if using UTF-8 this may actaully span multiple
620: * bytes in the input buffer.
621: *
622: * Returns the current char value and its lenght
623: */
624:
625: int
626: xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len) {
627: if (ctxt->encoding == NULL) {
628: /*
629: * We are supposed to handle UTF8, check it's valid
630: * From rfc2044: encoding of the Unicode values on UTF-8:
631: *
632: * UCS-4 range (hex.) UTF-8 octet sequence (binary)
633: * 0000 0000-0000 007F 0xxxxxxx
634: * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
635: * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
636: *
637: * Check for the 0x110000 limit too
638: */
639: unsigned char c;
640: unsigned int val;
641:
642: c = *cur;
643: if (c & 0x80) {
644: if ((cur[1] & 0xc0) != 0x80)
645: goto encoding_error;
646: if ((c & 0xe0) == 0xe0) {
647:
648: if ((cur[2] & 0xc0) != 0x80)
649: goto encoding_error;
650: if ((c & 0xf0) == 0xf0) {
651: if (((c & 0xf8) != 0xf0) ||
652: ((cur[3] & 0xc0) != 0x80))
653: goto encoding_error;
654: /* 4-byte code */
655: *len = 4;
656: val = (cur[0] & 0x7) << 18;
657: val |= (cur[1] & 0x3f) << 12;
658: val |= (cur[2] & 0x3f) << 6;
659: val |= cur[3] & 0x3f;
660: } else {
661: /* 3-byte code */
662: *len = 3;
663: val = (cur[0] & 0xf) << 12;
664: val |= (cur[1] & 0x3f) << 6;
665: val |= cur[2] & 0x3f;
666: }
667: } else {
668: /* 2-byte code */
669: *len = 2;
670: val = (cur[0] & 0x1f) << 6;
671: val |= cur[2] & 0x3f;
672: }
673: if (!IS_CHAR(val)) {
674: if ((ctxt->sax != NULL) &&
675: (ctxt->sax->error != NULL))
676: ctxt->sax->error(ctxt->userData,
677: "Char out of allowed range\n");
678: ctxt->errNo = XML_ERR_INVALID_ENCODING;
679: ctxt->wellFormed = 0;
680: }
681: return(val);
682: } else {
683: /* 1-byte code */
684: *len = 1;
685: return((int) *cur);
686: }
687: }
688: /*
689: * Assume it's a fixed lenght encoding (1) with
690: * a compatibke encoding for the ASCII set, since
691: * XML constructs only use < 128 chars
692: */
693: *len = 1;
694: return((int) *cur);
695: encoding_error:
696: /*
697: * If we detect an UTF8 error that probably mean that the
698: * input encoding didn't get properly advertized in the
699: * declaration header. Report the error and switch the encoding
700: * to ISO-Latin-1 (if you don't like this policy, just declare the
701: * encoding !)
702: */
703: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
704: ctxt->sax->error(ctxt->userData,
705: "Input is not proper UTF-8, indicate encoding !\n");
706: ctxt->errNo = XML_ERR_INVALID_ENCODING;
707:
708: *len = 1;
709: return((int) *cur);
710: }
711:
712: /**
1.152 daniel 713: * xmlCopyChar:
714: * @len: pointer to the length of the char read (or zero)
715: * @array: pointer to an arry of xmlChar
716: * @val: the char value
717: *
718: * append the char value in the array
719: *
720: * Returns the number of xmlChar written
721: */
722:
723: int
724: xmlCopyChar(int len, xmlChar *out, int val) {
725: /*
726: * We are supposed to handle UTF8, check it's valid
727: * From rfc2044: encoding of the Unicode values on UTF-8:
728: *
729: * UCS-4 range (hex.) UTF-8 octet sequence (binary)
730: * 0000 0000-0000 007F 0xxxxxxx
731: * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
732: * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
733: */
734: if (len == 0) {
735: if (val < 0) len = 0;
1.160 daniel 736: else if (val < 0x80) len = 1;
737: else if (val < 0x800) len = 2;
738: else if (val < 0x10000) len = 3;
739: else if (val < 0x110000) len = 4;
1.152 daniel 740: if (len == 0) {
741: fprintf(stderr, "Internal error, xmlCopyChar 0x%X out of bound\n",
742: val);
743: return(0);
744: }
745: }
746: if (len > 1) {
747: int bits;
748:
749: if (val < 0x80) { *out++= val; bits= -6; }
750: else if (val < 0x800) { *out++= (val >> 6) | 0xC0; bits= 0; }
751: else if (val < 0x10000) { *out++= (val >> 12) | 0xE0; bits= 6; }
752: else { *out++= (val >> 18) | 0xF0; bits= 12; }
753:
754: for ( ; bits >= 0; bits-= 6)
755: *out++= ((val >> bits) & 0x3F) | 0x80 ;
756:
757: return(len);
758: }
759: *out = (xmlChar) val;
760: return(1);
1.155 daniel 761: }
762:
763: /**
764: * xmlSkipBlankChars:
765: * @ctxt: the XML parser context
766: *
767: * skip all blanks character found at that point in the input streams.
768: * It pops up finished entities in the process if allowable at that point.
769: *
770: * Returns the number of space chars skipped
771: */
772:
773: int
774: xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
775: int cur, res = 0;
776:
777: do {
778: cur = CUR;
779: while (IS_BLANK(cur)) {
780: NEXT;
781: cur = CUR;
782: res++;
783: }
784: while ((cur == 0) && (ctxt->inputNr > 1) &&
785: (ctxt->instate != XML_PARSER_COMMENT)) {
786: xmlPopInput(ctxt);
787: cur = CUR;
788: }
789: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
790: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);
791: } while (IS_BLANK(cur));
792: return(res);
1.152 daniel 793: }
794:
1.97 daniel 795: /************************************************************************
796: * *
797: * Commodity functions to handle entities processing *
798: * *
799: ************************************************************************/
1.40 daniel 800:
1.50 daniel 801: /**
802: * xmlPopInput:
803: * @ctxt: an XML parser context
804: *
1.40 daniel 805: * xmlPopInput: the current input pointed by ctxt->input came to an end
806: * pop it and return the next char.
1.45 daniel 807: *
1.123 daniel 808: * Returns the current xmlChar in the parser context
1.40 daniel 809: */
1.123 daniel 810: xmlChar
1.55 daniel 811: xmlPopInput(xmlParserCtxtPtr ctxt) {
1.40 daniel 812: if (ctxt->inputNr == 1) return(0); /* End of main Input */
1.69 daniel 813: xmlFreeInputStream(inputPop(ctxt));
1.97 daniel 814: if ((*ctxt->input->cur == 0) &&
815: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
816: return(xmlPopInput(ctxt));
1.40 daniel 817: return(CUR);
818: }
819:
1.50 daniel 820: /**
821: * xmlPushInput:
822: * @ctxt: an XML parser context
823: * @input: an XML parser input fragment (entity, XML fragment ...).
824: *
1.40 daniel 825: * xmlPushInput: switch to a new input stream which is stacked on top
826: * of the previous one(s).
827: */
1.55 daniel 828: void
829: xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
1.40 daniel 830: if (input == NULL) return;
831: inputPush(ctxt, input);
1.164 daniel 832: GROW;
1.40 daniel 833: }
834:
1.50 daniel 835: /**
1.69 daniel 836: * xmlFreeInputStream:
1.127 daniel 837: * @input: an xmlParserInputPtr
1.69 daniel 838: *
839: * Free up an input stream.
840: */
841: void
842: xmlFreeInputStream(xmlParserInputPtr input) {
843: if (input == NULL) return;
844:
1.119 daniel 845: if (input->filename != NULL) xmlFree((char *) input->filename);
846: if (input->directory != NULL) xmlFree((char *) input->directory);
1.164 daniel 847: if (input->encoding != NULL) xmlFree((char *) input->encoding);
1.165 daniel 848: if (input->version != NULL) xmlFree((char *) input->version);
1.69 daniel 849: if ((input->free != NULL) && (input->base != NULL))
1.123 daniel 850: input->free((xmlChar *) input->base);
1.93 veillard 851: if (input->buf != NULL)
852: xmlFreeParserInputBuffer(input->buf);
1.69 daniel 853: memset(input, -1, sizeof(xmlParserInput));
1.119 daniel 854: xmlFree(input);
1.69 daniel 855: }
856:
857: /**
1.96 daniel 858: * xmlNewInputStream:
859: * @ctxt: an XML parser context
860: *
861: * Create a new input stream structure
862: * Returns the new input stream or NULL
863: */
864: xmlParserInputPtr
865: xmlNewInputStream(xmlParserCtxtPtr ctxt) {
866: xmlParserInputPtr input;
867:
1.119 daniel 868: input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
1.96 daniel 869: if (input == NULL) {
1.123 daniel 870: ctxt->errNo = XML_ERR_NO_MEMORY;
1.96 daniel 871: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 872: ctxt->sax->error(ctxt->userData,
873: "malloc: couldn't allocate a new input stream\n");
1.123 daniel 874: ctxt->errNo = XML_ERR_NO_MEMORY;
1.96 daniel 875: return(NULL);
876: }
1.165 daniel 877: memset(input, 0, sizeof(xmlParserInput));
1.96 daniel 878: input->line = 1;
879: input->col = 1;
1.167 daniel 880: input->standalone = -1;
1.96 daniel 881: return(input);
882: }
883:
884: /**
1.50 daniel 885: * xmlNewEntityInputStream:
886: * @ctxt: an XML parser context
887: * @entity: an Entity pointer
888: *
1.82 daniel 889: * Create a new input stream based on an xmlEntityPtr
1.113 daniel 890: *
891: * Returns the new input stream or NULL
1.45 daniel 892: */
1.50 daniel 893: xmlParserInputPtr
894: xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45 daniel 895: xmlParserInputPtr input;
896:
897: if (entity == NULL) {
1.123 daniel 898: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55 daniel 899: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 900: ctxt->sax->error(ctxt->userData,
1.45 daniel 901: "internal: xmlNewEntityInputStream entity = NULL\n");
1.123 daniel 902: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.50 daniel 903: return(NULL);
1.45 daniel 904: }
905: if (entity->content == NULL) {
1.159 daniel 906: switch (entity->etype) {
1.113 daniel 907: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.123 daniel 908: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.113 daniel 909: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
910: ctxt->sax->error(ctxt->userData,
911: "xmlNewEntityInputStream unparsed entity !\n");
912: break;
913: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
914: case XML_EXTERNAL_PARAMETER_ENTITY:
1.116 daniel 915: return(xmlLoadExternalEntity((char *) entity->SystemID,
1.142 daniel 916: (char *) entity->ExternalID, ctxt));
1.113 daniel 917: case XML_INTERNAL_GENERAL_ENTITY:
918: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
919: ctxt->sax->error(ctxt->userData,
920: "Internal entity %s without content !\n", entity->name);
921: break;
922: case XML_INTERNAL_PARAMETER_ENTITY:
1.123 daniel 923: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113 daniel 924: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
925: ctxt->sax->error(ctxt->userData,
926: "Internal parameter entity %s without content !\n", entity->name);
927: break;
928: case XML_INTERNAL_PREDEFINED_ENTITY:
1.123 daniel 929: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113 daniel 930: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
931: ctxt->sax->error(ctxt->userData,
932: "Predefined entity %s without content !\n", entity->name);
933: break;
934: }
1.50 daniel 935: return(NULL);
1.45 daniel 936: }
1.96 daniel 937: input = xmlNewInputStream(ctxt);
1.45 daniel 938: if (input == NULL) {
1.50 daniel 939: return(NULL);
1.45 daniel 940: }
1.156 daniel 941: input->filename = (char *) entity->SystemID;
1.45 daniel 942: input->base = entity->content;
943: input->cur = entity->content;
1.140 daniel 944: input->length = entity->length;
1.50 daniel 945: return(input);
1.45 daniel 946: }
947:
1.59 daniel 948: /**
949: * xmlNewStringInputStream:
950: * @ctxt: an XML parser context
1.96 daniel 951: * @buffer: an memory buffer
1.59 daniel 952: *
953: * Create a new input stream based on a memory buffer.
1.68 daniel 954: * Returns the new input stream
1.59 daniel 955: */
956: xmlParserInputPtr
1.123 daniel 957: xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
1.59 daniel 958: xmlParserInputPtr input;
959:
1.96 daniel 960: if (buffer == NULL) {
1.123 daniel 961: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 962: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 963: ctxt->sax->error(ctxt->userData,
1.59 daniel 964: "internal: xmlNewStringInputStream string = NULL\n");
965: return(NULL);
966: }
1.96 daniel 967: input = xmlNewInputStream(ctxt);
1.59 daniel 968: if (input == NULL) {
969: return(NULL);
970: }
1.96 daniel 971: input->base = buffer;
972: input->cur = buffer;
1.140 daniel 973: input->length = xmlStrlen(buffer);
1.59 daniel 974: return(input);
975: }
976:
1.76 daniel 977: /**
978: * xmlNewInputFromFile:
979: * @ctxt: an XML parser context
980: * @filename: the filename to use as entity
981: *
982: * Create a new input stream based on a file.
983: *
984: * Returns the new input stream or NULL in case of error
985: */
986: xmlParserInputPtr
1.79 daniel 987: xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
1.91 daniel 988: xmlParserInputBufferPtr buf;
1.76 daniel 989: xmlParserInputPtr inputStream;
1.111 daniel 990: char *directory = NULL;
1.76 daniel 991:
1.96 daniel 992: if (ctxt == NULL) return(NULL);
1.91 daniel 993: buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1.94 daniel 994: if (buf == NULL) {
1.140 daniel 995: char name[XML_PARSER_BIG_BUFFER_SIZE];
1.106 daniel 996:
1.94 daniel 997: if ((ctxt->input != NULL) && (ctxt->input->directory != NULL)) {
998: #ifdef WIN32
999: sprintf(name, "%s\\%s", ctxt->input->directory, filename);
1000: #else
1001: sprintf(name, "%s/%s", ctxt->input->directory, filename);
1002: #endif
1003: buf = xmlParserInputBufferCreateFilename(name,
1004: XML_CHAR_ENCODING_NONE);
1.106 daniel 1005: if (buf != NULL)
1.142 daniel 1006: directory = xmlParserGetDirectory(name);
1.106 daniel 1007: }
1008: if ((buf == NULL) && (ctxt->directory != NULL)) {
1009: #ifdef WIN32
1010: sprintf(name, "%s\\%s", ctxt->directory, filename);
1011: #else
1012: sprintf(name, "%s/%s", ctxt->directory, filename);
1013: #endif
1014: buf = xmlParserInputBufferCreateFilename(name,
1015: XML_CHAR_ENCODING_NONE);
1016: if (buf != NULL)
1.142 daniel 1017: directory = xmlParserGetDirectory(name);
1.106 daniel 1018: }
1019: if (buf == NULL)
1.94 daniel 1020: return(NULL);
1021: }
1022: if (directory == NULL)
1023: directory = xmlParserGetDirectory(filename);
1.76 daniel 1024:
1.96 daniel 1025: inputStream = xmlNewInputStream(ctxt);
1.76 daniel 1026: if (inputStream == NULL) {
1.119 daniel 1027: if (directory != NULL) xmlFree((char *) directory);
1.76 daniel 1028: return(NULL);
1029: }
1030:
1.119 daniel 1031: inputStream->filename = xmlMemStrdup(filename);
1.94 daniel 1032: inputStream->directory = directory;
1.91 daniel 1033: inputStream->buf = buf;
1.76 daniel 1034:
1.91 daniel 1035: inputStream->base = inputStream->buf->buffer->content;
1036: inputStream->cur = inputStream->buf->buffer->content;
1.106 daniel 1037: if ((ctxt->directory == NULL) && (directory != NULL))
1.134 daniel 1038: ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory);
1.76 daniel 1039: return(inputStream);
1040: }
1041:
1.77 daniel 1042: /************************************************************************
1043: * *
1.97 daniel 1044: * Commodity functions to handle parser contexts *
1045: * *
1046: ************************************************************************/
1047:
1048: /**
1049: * xmlInitParserCtxt:
1050: * @ctxt: an XML parser context
1051: *
1052: * Initialize a parser context
1053: */
1054:
1055: void
1056: xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
1057: {
1058: xmlSAXHandler *sax;
1059:
1.168 daniel 1060: xmlDefaultSAXHandlerInit();
1061:
1.119 daniel 1062: sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1.97 daniel 1063: if (sax == NULL) {
1064: fprintf(stderr, "xmlInitParserCtxt: out of memory\n");
1065: }
1066:
1067: /* Allocate the Input stack */
1.119 daniel 1068: ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr));
1.97 daniel 1069: ctxt->inputNr = 0;
1070: ctxt->inputMax = 5;
1071: ctxt->input = NULL;
1.165 daniel 1072:
1.97 daniel 1073: ctxt->version = NULL;
1074: ctxt->encoding = NULL;
1075: ctxt->standalone = -1;
1.98 daniel 1076: ctxt->hasExternalSubset = 0;
1077: ctxt->hasPErefs = 0;
1.97 daniel 1078: ctxt->html = 0;
1.98 daniel 1079: ctxt->external = 0;
1.140 daniel 1080: ctxt->instate = XML_PARSER_START;
1.97 daniel 1081: ctxt->token = 0;
1.106 daniel 1082: ctxt->directory = NULL;
1.97 daniel 1083:
1084: /* Allocate the Node stack */
1.119 daniel 1085: ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
1.97 daniel 1086: ctxt->nodeNr = 0;
1087: ctxt->nodeMax = 10;
1088: ctxt->node = NULL;
1089:
1.140 daniel 1090: /* Allocate the Name stack */
1091: ctxt->nameTab = (xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
1092: ctxt->nameNr = 0;
1093: ctxt->nameMax = 10;
1094: ctxt->name = NULL;
1095:
1.160 daniel 1096: if (sax == NULL) {
1097: ctxt->sax = &xmlDefaultSAXHandler;
1098: } else {
1.97 daniel 1099: ctxt->sax = sax;
1100: memcpy(sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
1101: }
1102: ctxt->userData = ctxt;
1103: ctxt->myDoc = NULL;
1104: ctxt->wellFormed = 1;
1.99 daniel 1105: ctxt->valid = 1;
1.100 daniel 1106: ctxt->validate = xmlDoValidityCheckingDefaultValue;
1107: ctxt->vctxt.userData = ctxt;
1.149 daniel 1108: if (ctxt->validate) {
1109: ctxt->vctxt.error = xmlParserValidityError;
1.160 daniel 1110: if (xmlGetWarningsDefaultValue == 0)
1111: ctxt->vctxt.warning = NULL;
1112: else
1113: ctxt->vctxt.warning = xmlParserValidityWarning;
1.149 daniel 1114: } else {
1115: ctxt->vctxt.error = NULL;
1116: ctxt->vctxt.warning = NULL;
1117: }
1.97 daniel 1118: ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
1119: ctxt->record_info = 0;
1.135 daniel 1120: ctxt->nbChars = 0;
1.140 daniel 1121: ctxt->checkIndex = 0;
1122: ctxt->errNo = XML_ERR_OK;
1.97 daniel 1123: xmlInitNodeInfoSeq(&ctxt->node_seq);
1124: }
1125:
1126: /**
1127: * xmlFreeParserCtxt:
1128: * @ctxt: an XML parser context
1129: *
1130: * Free all the memory used by a parser context. However the parsed
1131: * document in ctxt->myDoc is not freed.
1132: */
1133:
1134: void
1135: xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
1136: {
1137: xmlParserInputPtr input;
1.140 daniel 1138: xmlChar *oldname;
1.97 daniel 1139:
1140: if (ctxt == NULL) return;
1141:
1142: while ((input = inputPop(ctxt)) != NULL) {
1143: xmlFreeInputStream(input);
1144: }
1.140 daniel 1145: while ((oldname = namePop(ctxt)) != NULL) {
1146: xmlFree(oldname);
1147: }
1148: if (ctxt->nameTab != NULL) xmlFree(ctxt->nameTab);
1.119 daniel 1149: if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
1150: if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
1151: if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
1152: if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
1.165 daniel 1153: if (ctxt->intSubName != NULL) xmlFree((char *) ctxt->intSubName);
1154: if (ctxt->extSubURI != NULL) xmlFree((char *) ctxt->extSubURI);
1155: if (ctxt->extSubSystem != NULL) xmlFree((char *) ctxt->extSubSystem);
1.97 daniel 1156: if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
1.119 daniel 1157: xmlFree(ctxt->sax);
1158: if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
1159: xmlFree(ctxt);
1.97 daniel 1160: }
1161:
1162: /**
1163: * xmlNewParserCtxt:
1164: *
1165: * Allocate and initialize a new parser context.
1166: *
1167: * Returns the xmlParserCtxtPtr or NULL
1168: */
1169:
1170: xmlParserCtxtPtr
1171: xmlNewParserCtxt()
1172: {
1173: xmlParserCtxtPtr ctxt;
1174:
1.119 daniel 1175: ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
1.97 daniel 1176: if (ctxt == NULL) {
1177: fprintf(stderr, "xmlNewParserCtxt : cannot allocate context\n");
1178: perror("malloc");
1179: return(NULL);
1180: }
1.165 daniel 1181: memset(ctxt, 0, sizeof(xmlParserCtxt));
1.97 daniel 1182: xmlInitParserCtxt(ctxt);
1183: return(ctxt);
1184: }
1185:
1186: /**
1187: * xmlClearParserCtxt:
1188: * @ctxt: an XML parser context
1189: *
1190: * Clear (release owned resources) and reinitialize a parser context
1191: */
1192:
1193: void
1194: xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
1195: {
1196: xmlClearNodeInfoSeq(&ctxt->node_seq);
1197: xmlInitParserCtxt(ctxt);
1198: }
1199:
1200: /************************************************************************
1201: * *
1.77 daniel 1202: * Commodity functions to handle entities *
1203: * *
1204: ************************************************************************/
1205:
1.97 daniel 1206:
1207: /**
1208: * xmlParseCharRef:
1209: * @ctxt: an XML parser context
1210: *
1211: * parse Reference declarations
1212: *
1213: * [66] CharRef ::= '&#' [0-9]+ ';' |
1214: * '&#x' [0-9a-fA-F]+ ';'
1215: *
1.98 daniel 1216: * [ WFC: Legal Character ]
1217: * Characters referred to using character references must match the
1218: * production for Char.
1219: *
1.135 daniel 1220: * Returns the value parsed (as an int), 0 in case of error
1.77 daniel 1221: */
1.97 daniel 1222: int
1223: xmlParseCharRef(xmlParserCtxtPtr ctxt) {
1224: int val = 0;
1225:
1.111 daniel 1226: if (ctxt->token != 0) {
1227: val = ctxt->token;
1228: ctxt->token = 0;
1229: return(val);
1230: }
1.152 daniel 1231: if ((RAW == '&') && (NXT(1) == '#') &&
1.97 daniel 1232: (NXT(2) == 'x')) {
1233: SKIP(3);
1.152 daniel 1234: while (RAW != ';') {
1235: if ((RAW >= '0') && (RAW <= '9'))
1.97 daniel 1236: val = val * 16 + (CUR - '0');
1.152 daniel 1237: else if ((RAW >= 'a') && (RAW <= 'f'))
1.97 daniel 1238: val = val * 16 + (CUR - 'a') + 10;
1.152 daniel 1239: else if ((RAW >= 'A') && (RAW <= 'F'))
1.97 daniel 1240: val = val * 16 + (CUR - 'A') + 10;
1241: else {
1.123 daniel 1242: ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
1.97 daniel 1243: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1244: ctxt->sax->error(ctxt->userData,
1245: "xmlParseCharRef: invalid hexadecimal value\n");
1246: ctxt->wellFormed = 0;
1247: val = 0;
1248: break;
1249: }
1250: NEXT;
1251: }
1.164 daniel 1252: if (RAW == ';') {
1253: /* on purpose to avoid reentrancy problems with NEXT and SKIP */
1254: ctxt->nbChars ++;
1255: ctxt->input->cur++;
1256: }
1.152 daniel 1257: } else if ((RAW == '&') && (NXT(1) == '#')) {
1.97 daniel 1258: SKIP(2);
1.152 daniel 1259: while (RAW != ';') {
1260: if ((RAW >= '0') && (RAW <= '9'))
1.97 daniel 1261: val = val * 10 + (CUR - '0');
1262: else {
1.123 daniel 1263: ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
1.97 daniel 1264: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1265: ctxt->sax->error(ctxt->userData,
1266: "xmlParseCharRef: invalid decimal value\n");
1267: ctxt->wellFormed = 0;
1268: val = 0;
1269: break;
1270: }
1271: NEXT;
1272: }
1.164 daniel 1273: if (RAW == ';') {
1274: /* on purpose to avoid reentrancy problems with NEXT and SKIP */
1275: ctxt->nbChars ++;
1276: ctxt->input->cur++;
1277: }
1.97 daniel 1278: } else {
1.123 daniel 1279: ctxt->errNo = XML_ERR_INVALID_CHARREF;
1.97 daniel 1280: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 1281: ctxt->sax->error(ctxt->userData,
1282: "xmlParseCharRef: invalid value\n");
1.97 daniel 1283: ctxt->wellFormed = 0;
1284: }
1.98 daniel 1285:
1.97 daniel 1286: /*
1.98 daniel 1287: * [ WFC: Legal Character ]
1288: * Characters referred to using character references must match the
1289: * production for Char.
1.97 daniel 1290: */
1291: if (IS_CHAR(val)) {
1292: return(val);
1293: } else {
1.123 daniel 1294: ctxt->errNo = XML_ERR_INVALID_CHAR;
1.97 daniel 1295: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.123 daniel 1296: ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
1.97 daniel 1297: val);
1298: ctxt->wellFormed = 0;
1299: }
1300: return(0);
1.77 daniel 1301: }
1302:
1.96 daniel 1303: /**
1.135 daniel 1304: * xmlParseStringCharRef:
1305: * @ctxt: an XML parser context
1306: * @str: a pointer to an index in the string
1307: *
1308: * parse Reference declarations, variant parsing from a string rather
1309: * than an an input flow.
1310: *
1311: * [66] CharRef ::= '&#' [0-9]+ ';' |
1312: * '&#x' [0-9a-fA-F]+ ';'
1313: *
1314: * [ WFC: Legal Character ]
1315: * Characters referred to using character references must match the
1316: * production for Char.
1317: *
1318: * Returns the value parsed (as an int), 0 in case of error, str will be
1319: * updated to the current value of the index
1320: */
1321: int
1322: xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
1323: const xmlChar *ptr;
1324: xmlChar cur;
1325: int val = 0;
1326:
1327: if ((str == NULL) || (*str == NULL)) return(0);
1328: ptr = *str;
1329: cur = *ptr;
1.137 daniel 1330: if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
1.135 daniel 1331: ptr += 3;
1332: cur = *ptr;
1333: while (cur != ';') {
1334: if ((cur >= '0') && (cur <= '9'))
1335: val = val * 16 + (cur - '0');
1336: else if ((cur >= 'a') && (cur <= 'f'))
1337: val = val * 16 + (cur - 'a') + 10;
1338: else if ((cur >= 'A') && (cur <= 'F'))
1339: val = val * 16 + (cur - 'A') + 10;
1340: else {
1341: ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
1342: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1343: ctxt->sax->error(ctxt->userData,
1344: "xmlParseCharRef: invalid hexadecimal value\n");
1345: ctxt->wellFormed = 0;
1346: val = 0;
1347: break;
1348: }
1349: ptr++;
1350: cur = *ptr;
1351: }
1352: if (cur == ';')
1353: ptr++;
1.145 daniel 1354: } else if ((cur == '&') && (ptr[1] == '#')){
1.135 daniel 1355: ptr += 2;
1356: cur = *ptr;
1357: while (cur != ';') {
1358: if ((cur >= '0') && (cur <= '9'))
1359: val = val * 10 + (cur - '0');
1360: else {
1361: ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
1362: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1363: ctxt->sax->error(ctxt->userData,
1364: "xmlParseCharRef: invalid decimal value\n");
1365: ctxt->wellFormed = 0;
1366: val = 0;
1367: break;
1368: }
1369: ptr++;
1370: cur = *ptr;
1371: }
1372: if (cur == ';')
1373: ptr++;
1374: } else {
1375: ctxt->errNo = XML_ERR_INVALID_CHARREF;
1376: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1377: ctxt->sax->error(ctxt->userData,
1378: "xmlParseCharRef: invalid value\n");
1379: ctxt->wellFormed = 0;
1380: return(0);
1381: }
1382: *str = ptr;
1383:
1384: /*
1385: * [ WFC: Legal Character ]
1386: * Characters referred to using character references must match the
1387: * production for Char.
1388: */
1389: if (IS_CHAR(val)) {
1390: return(val);
1391: } else {
1392: ctxt->errNo = XML_ERR_INVALID_CHAR;
1393: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1394: ctxt->sax->error(ctxt->userData,
1395: "CharRef: invalid xmlChar value %d\n", val);
1396: ctxt->wellFormed = 0;
1397: }
1398: return(0);
1399: }
1400:
1401: /**
1.96 daniel 1402: * xmlParserHandleReference:
1403: * @ctxt: the parser context
1404: *
1.97 daniel 1405: * [67] Reference ::= EntityRef | CharRef
1406: *
1.96 daniel 1407: * [68] EntityRef ::= '&' Name ';'
1408: *
1.98 daniel 1409: * [ WFC: Entity Declared ]
1410: * the Name given in the entity reference must match that in an entity
1411: * declaration, except that well-formed documents need not declare any
1412: * of the following entities: amp, lt, gt, apos, quot.
1413: *
1414: * [ WFC: Parsed Entity ]
1415: * An entity reference must not contain the name of an unparsed entity
1416: *
1.97 daniel 1417: * [66] CharRef ::= '&#' [0-9]+ ';' |
1418: * '&#x' [0-9a-fA-F]+ ';'
1419: *
1.96 daniel 1420: * A PEReference may have been detectect in the current input stream
1421: * the handling is done accordingly to
1422: * http://www.w3.org/TR/REC-xml#entproc
1423: */
1424: void
1425: xmlParserHandleReference(xmlParserCtxtPtr ctxt) {
1.97 daniel 1426: xmlParserInputPtr input;
1.123 daniel 1427: xmlChar *name;
1.97 daniel 1428: xmlEntityPtr ent = NULL;
1429:
1.126 daniel 1430: if (ctxt->token != 0) {
1431: return;
1432: }
1.152 daniel 1433: if (RAW != '&') return;
1.97 daniel 1434: GROW;
1.152 daniel 1435: if ((RAW == '&') && (NXT(1) == '#')) {
1.97 daniel 1436: switch(ctxt->instate) {
1.140 daniel 1437: case XML_PARSER_ENTITY_DECL:
1438: case XML_PARSER_PI:
1.109 daniel 1439: case XML_PARSER_CDATA_SECTION:
1.140 daniel 1440: case XML_PARSER_COMMENT:
1.168 daniel 1441: case XML_PARSER_SYSTEM_LITERAL:
1.140 daniel 1442: /* we just ignore it there */
1443: return;
1444: case XML_PARSER_START_TAG:
1.109 daniel 1445: return;
1.140 daniel 1446: case XML_PARSER_END_TAG:
1.97 daniel 1447: return;
1448: case XML_PARSER_EOF:
1.123 daniel 1449: ctxt->errNo = XML_ERR_CHARREF_AT_EOF;
1.97 daniel 1450: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1451: ctxt->sax->error(ctxt->userData, "CharRef at EOF\n");
1452: ctxt->wellFormed = 0;
1453: return;
1454: case XML_PARSER_PROLOG:
1.140 daniel 1455: case XML_PARSER_START:
1456: case XML_PARSER_MISC:
1.123 daniel 1457: ctxt->errNo = XML_ERR_CHARREF_IN_PROLOG;
1.97 daniel 1458: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1459: ctxt->sax->error(ctxt->userData, "CharRef in prolog!\n");
1460: ctxt->wellFormed = 0;
1461: return;
1462: case XML_PARSER_EPILOG:
1.123 daniel 1463: ctxt->errNo = XML_ERR_CHARREF_IN_EPILOG;
1.97 daniel 1464: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1465: ctxt->sax->error(ctxt->userData, "CharRef in epilog!\n");
1466: ctxt->wellFormed = 0;
1467: return;
1468: case XML_PARSER_DTD:
1.123 daniel 1469: ctxt->errNo = XML_ERR_CHARREF_IN_DTD;
1.97 daniel 1470: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1471: ctxt->sax->error(ctxt->userData,
1472: "CharRef are forbiden in DTDs!\n");
1473: ctxt->wellFormed = 0;
1474: return;
1475: case XML_PARSER_ENTITY_VALUE:
1476: /*
1477: * NOTE: in the case of entity values, we don't do the
1.127 daniel 1478: * substitution here since we need the literal
1.97 daniel 1479: * entity value to be able to save the internal
1480: * subset of the document.
1481: * This will be handled by xmlDecodeEntities
1482: */
1483: return;
1484: case XML_PARSER_CONTENT:
1485: case XML_PARSER_ATTRIBUTE_VALUE:
1486: ctxt->token = xmlParseCharRef(ctxt);
1487: return;
1488: }
1489: return;
1490: }
1491:
1492: switch(ctxt->instate) {
1.109 daniel 1493: case XML_PARSER_CDATA_SECTION:
1494: return;
1.140 daniel 1495: case XML_PARSER_PI:
1.97 daniel 1496: case XML_PARSER_COMMENT:
1.168 daniel 1497: case XML_PARSER_SYSTEM_LITERAL:
1498: case XML_PARSER_CONTENT:
1.97 daniel 1499: return;
1.140 daniel 1500: case XML_PARSER_START_TAG:
1501: return;
1502: case XML_PARSER_END_TAG:
1503: return;
1.97 daniel 1504: case XML_PARSER_EOF:
1.123 daniel 1505: ctxt->errNo = XML_ERR_ENTITYREF_AT_EOF;
1.97 daniel 1506: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1507: ctxt->sax->error(ctxt->userData, "Reference at EOF\n");
1508: ctxt->wellFormed = 0;
1509: return;
1510: case XML_PARSER_PROLOG:
1.140 daniel 1511: case XML_PARSER_START:
1512: case XML_PARSER_MISC:
1.123 daniel 1513: ctxt->errNo = XML_ERR_ENTITYREF_IN_PROLOG;
1.97 daniel 1514: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1515: ctxt->sax->error(ctxt->userData, "Reference in prolog!\n");
1516: ctxt->wellFormed = 0;
1517: return;
1518: case XML_PARSER_EPILOG:
1.123 daniel 1519: ctxt->errNo = XML_ERR_ENTITYREF_IN_EPILOG;
1.97 daniel 1520: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1521: ctxt->sax->error(ctxt->userData, "Reference in epilog!\n");
1522: ctxt->wellFormed = 0;
1523: return;
1524: case XML_PARSER_ENTITY_VALUE:
1525: /*
1526: * NOTE: in the case of entity values, we don't do the
1.127 daniel 1527: * substitution here since we need the literal
1.97 daniel 1528: * entity value to be able to save the internal
1529: * subset of the document.
1530: * This will be handled by xmlDecodeEntities
1531: */
1532: return;
1533: case XML_PARSER_ATTRIBUTE_VALUE:
1534: /*
1535: * NOTE: in the case of attributes values, we don't do the
1536: * substitution here unless we are in a mode where
1537: * the parser is explicitely asked to substitute
1538: * entities. The SAX callback is called with values
1539: * without entity substitution.
1540: * This will then be handled by xmlDecodeEntities
1541: */
1.113 daniel 1542: return;
1.97 daniel 1543: case XML_PARSER_ENTITY_DECL:
1544: /*
1545: * we just ignore it there
1546: * the substitution will be done once the entity is referenced
1547: */
1548: return;
1549: case XML_PARSER_DTD:
1.123 daniel 1550: ctxt->errNo = XML_ERR_ENTITYREF_IN_DTD;
1.97 daniel 1551: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1552: ctxt->sax->error(ctxt->userData,
1553: "Entity references are forbiden in DTDs!\n");
1554: ctxt->wellFormed = 0;
1555: return;
1556: }
1557:
1558: NEXT;
1559: name = xmlScanName(ctxt);
1560: if (name == NULL) {
1.123 daniel 1561: ctxt->errNo = XML_ERR_ENTITYREF_NO_NAME;
1.97 daniel 1562: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1563: ctxt->sax->error(ctxt->userData, "Entity reference: no name\n");
1564: ctxt->wellFormed = 0;
1565: ctxt->token = '&';
1566: return;
1567: }
1568: if (NXT(xmlStrlen(name)) != ';') {
1.123 daniel 1569: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.97 daniel 1570: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1571: ctxt->sax->error(ctxt->userData,
1572: "Entity reference: ';' expected\n");
1573: ctxt->wellFormed = 0;
1574: ctxt->token = '&';
1.119 daniel 1575: xmlFree(name);
1.97 daniel 1576: return;
1577: }
1578: SKIP(xmlStrlen(name) + 1);
1579: if (ctxt->sax != NULL) {
1580: if (ctxt->sax->getEntity != NULL)
1581: ent = ctxt->sax->getEntity(ctxt->userData, name);
1582: }
1.98 daniel 1583:
1584: /*
1585: * [ WFC: Entity Declared ]
1586: * the Name given in the entity reference must match that in an entity
1587: * declaration, except that well-formed documents need not declare any
1588: * of the following entities: amp, lt, gt, apos, quot.
1589: */
1.97 daniel 1590: if (ent == NULL)
1591: ent = xmlGetPredefinedEntity(name);
1592: if (ent == NULL) {
1.123 daniel 1593: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.97 daniel 1594: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1595: ctxt->sax->error(ctxt->userData,
1.98 daniel 1596: "Entity reference: entity %s not declared\n",
1597: name);
1.97 daniel 1598: ctxt->wellFormed = 0;
1.119 daniel 1599: xmlFree(name);
1.97 daniel 1600: return;
1601: }
1.98 daniel 1602:
1603: /*
1604: * [ WFC: Parsed Entity ]
1605: * An entity reference must not contain the name of an unparsed entity
1606: */
1.159 daniel 1607: if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1.123 daniel 1608: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98 daniel 1609: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1610: ctxt->sax->error(ctxt->userData,
1611: "Entity reference to unparsed entity %s\n", name);
1612: ctxt->wellFormed = 0;
1613: }
1614:
1.159 daniel 1615: if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) {
1.97 daniel 1616: ctxt->token = ent->content[0];
1.119 daniel 1617: xmlFree(name);
1.97 daniel 1618: return;
1619: }
1620: input = xmlNewEntityInputStream(ctxt, ent);
1621: xmlPushInput(ctxt, input);
1.119 daniel 1622: xmlFree(name);
1.96 daniel 1623: return;
1624: }
1625:
1626: /**
1627: * xmlParserHandlePEReference:
1628: * @ctxt: the parser context
1629: *
1630: * [69] PEReference ::= '%' Name ';'
1631: *
1.98 daniel 1632: * [ WFC: No Recursion ]
1633: * TODO A parsed entity must not contain a recursive
1634: * reference to itself, either directly or indirectly.
1635: *
1636: * [ WFC: Entity Declared ]
1637: * In a document without any DTD, a document with only an internal DTD
1638: * subset which contains no parameter entity references, or a document
1639: * with "standalone='yes'", ... ... The declaration of a parameter
1640: * entity must precede any reference to it...
1641: *
1642: * [ VC: Entity Declared ]
1643: * In a document with an external subset or external parameter entities
1644: * with "standalone='no'", ... ... The declaration of a parameter entity
1645: * must precede any reference to it...
1646: *
1647: * [ WFC: In DTD ]
1648: * Parameter-entity references may only appear in the DTD.
1649: * NOTE: misleading but this is handled.
1650: *
1651: * A PEReference may have been detected in the current input stream
1.96 daniel 1652: * the handling is done accordingly to
1653: * http://www.w3.org/TR/REC-xml#entproc
1654: * i.e.
1655: * - Included in literal in entity values
1656: * - Included as Paraemeter Entity reference within DTDs
1657: */
1658: void
1659: xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
1.123 daniel 1660: xmlChar *name;
1.96 daniel 1661: xmlEntityPtr entity = NULL;
1662: xmlParserInputPtr input;
1663:
1.126 daniel 1664: if (ctxt->token != 0) {
1665: return;
1666: }
1.152 daniel 1667: if (RAW != '%') return;
1.96 daniel 1668: switch(ctxt->instate) {
1.109 daniel 1669: case XML_PARSER_CDATA_SECTION:
1670: return;
1.97 daniel 1671: case XML_PARSER_COMMENT:
1672: return;
1.140 daniel 1673: case XML_PARSER_START_TAG:
1674: return;
1675: case XML_PARSER_END_TAG:
1676: return;
1.96 daniel 1677: case XML_PARSER_EOF:
1.123 daniel 1678: ctxt->errNo = XML_ERR_PEREF_AT_EOF;
1.96 daniel 1679: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1680: ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
1681: ctxt->wellFormed = 0;
1682: return;
1683: case XML_PARSER_PROLOG:
1.140 daniel 1684: case XML_PARSER_START:
1685: case XML_PARSER_MISC:
1.123 daniel 1686: ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
1.96 daniel 1687: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1688: ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
1689: ctxt->wellFormed = 0;
1690: return;
1.97 daniel 1691: case XML_PARSER_ENTITY_DECL:
1.96 daniel 1692: case XML_PARSER_CONTENT:
1693: case XML_PARSER_ATTRIBUTE_VALUE:
1.140 daniel 1694: case XML_PARSER_PI:
1.168 daniel 1695: case XML_PARSER_SYSTEM_LITERAL:
1.96 daniel 1696: /* we just ignore it there */
1697: return;
1698: case XML_PARSER_EPILOG:
1.123 daniel 1699: ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
1.96 daniel 1700: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.97 daniel 1701: ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
1.96 daniel 1702: ctxt->wellFormed = 0;
1703: return;
1.97 daniel 1704: case XML_PARSER_ENTITY_VALUE:
1705: /*
1706: * NOTE: in the case of entity values, we don't do the
1.127 daniel 1707: * substitution here since we need the literal
1.97 daniel 1708: * entity value to be able to save the internal
1709: * subset of the document.
1710: * This will be handled by xmlDecodeEntities
1711: */
1712: return;
1.96 daniel 1713: case XML_PARSER_DTD:
1.98 daniel 1714: /*
1715: * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
1716: * In the internal DTD subset, parameter-entity references
1717: * can occur only where markup declarations can occur, not
1718: * within markup declarations.
1719: * In that case this is handled in xmlParseMarkupDecl
1720: */
1721: if ((ctxt->external == 0) && (ctxt->inputNr == 1))
1722: return;
1.96 daniel 1723: }
1724:
1725: NEXT;
1726: name = xmlParseName(ctxt);
1727: if (name == NULL) {
1.123 daniel 1728: ctxt->errNo = XML_ERR_PEREF_NO_NAME;
1.96 daniel 1729: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1730: ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
1731: ctxt->wellFormed = 0;
1732: } else {
1.152 daniel 1733: if (RAW == ';') {
1.96 daniel 1734: NEXT;
1.98 daniel 1735: if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
1736: entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.96 daniel 1737: if (entity == NULL) {
1.98 daniel 1738:
1739: /*
1740: * [ WFC: Entity Declared ]
1741: * In a document without any DTD, a document with only an
1742: * internal DTD subset which contains no parameter entity
1743: * references, or a document with "standalone='yes'", ...
1744: * ... The declaration of a parameter entity must precede
1745: * any reference to it...
1746: */
1747: if ((ctxt->standalone == 1) ||
1748: ((ctxt->hasExternalSubset == 0) &&
1749: (ctxt->hasPErefs == 0))) {
1750: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1751: ctxt->sax->error(ctxt->userData,
1752: "PEReference: %%%s; not found\n", name);
1753: ctxt->wellFormed = 0;
1754: } else {
1755: /*
1756: * [ VC: Entity Declared ]
1757: * In a document with an external subset or external
1758: * parameter entities with "standalone='no'", ...
1759: * ... The declaration of a parameter entity must precede
1760: * any reference to it...
1761: */
1762: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1763: ctxt->sax->warning(ctxt->userData,
1764: "PEReference: %%%s; not found\n", name);
1765: ctxt->valid = 0;
1766: }
1.96 daniel 1767: } else {
1.159 daniel 1768: if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
1769: (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
1.96 daniel 1770: /*
1.156 daniel 1771: * TODO !!! handle the extra spaces added before and after
1.96 daniel 1772: * c.f. http://www.w3.org/TR/REC-xml#as-PE
1773: */
1774: input = xmlNewEntityInputStream(ctxt, entity);
1775: xmlPushInput(ctxt, input);
1.164 daniel 1776: if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
1777: (RAW == '<') && (NXT(1) == '?') &&
1778: (NXT(2) == 'x') && (NXT(3) == 'm') &&
1779: (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
1780: xmlParseXMLDecl(ctxt);
1781: }
1782: if (ctxt->token == 0)
1783: ctxt->token = ' ';
1.96 daniel 1784: } else {
1785: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1786: ctxt->sax->error(ctxt->userData,
1787: "xmlHandlePEReference: %s is not a parameter entity\n",
1788: name);
1789: ctxt->wellFormed = 0;
1790: }
1791: }
1792: } else {
1.123 daniel 1793: ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
1.96 daniel 1794: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1795: ctxt->sax->error(ctxt->userData,
1796: "xmlHandlePEReference: expecting ';'\n");
1797: ctxt->wellFormed = 0;
1798: }
1.119 daniel 1799: xmlFree(name);
1.97 daniel 1800: }
1801: }
1802:
1803: /*
1804: * Macro used to grow the current buffer.
1805: */
1806: #define growBuffer(buffer) { \
1807: buffer##_size *= 2; \
1.145 daniel 1808: buffer = (xmlChar *) \
1809: xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
1.97 daniel 1810: if (buffer == NULL) { \
1811: perror("realloc failed"); \
1.145 daniel 1812: return(NULL); \
1.97 daniel 1813: } \
1.96 daniel 1814: }
1.77 daniel 1815:
1816: /**
1817: * xmlDecodeEntities:
1818: * @ctxt: the parser context
1819: * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1820: * @len: the len to decode (in bytes !), -1 for no size limit
1.123 daniel 1821: * @end: an end marker xmlChar, 0 if none
1822: * @end2: an end marker xmlChar, 0 if none
1823: * @end3: an end marker xmlChar, 0 if none
1.77 daniel 1824: *
1825: * [67] Reference ::= EntityRef | CharRef
1826: *
1827: * [69] PEReference ::= '%' Name ';'
1828: *
1829: * Returns A newly allocated string with the substitution done. The caller
1830: * must deallocate it !
1831: */
1.123 daniel 1832: xmlChar *
1.77 daniel 1833: xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
1.123 daniel 1834: xmlChar end, xmlChar end2, xmlChar end3) {
1835: xmlChar *buffer = NULL;
1.78 daniel 1836: int buffer_size = 0;
1.161 daniel 1837: int nbchars = 0;
1.78 daniel 1838:
1.123 daniel 1839: xmlChar *current = NULL;
1.77 daniel 1840: xmlEntityPtr ent;
1841: unsigned int max = (unsigned int) len;
1.161 daniel 1842: int c,l;
1.77 daniel 1843:
1844: /*
1845: * allocate a translation buffer.
1846: */
1.140 daniel 1847: buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
1.123 daniel 1848: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.77 daniel 1849: if (buffer == NULL) {
1850: perror("xmlDecodeEntities: malloc failed");
1851: return(NULL);
1852: }
1853:
1.78 daniel 1854: /*
1855: * Ok loop until we reach one of the ending char or a size limit.
1856: */
1.161 daniel 1857: c = CUR_CHAR(l);
1858: while ((nbchars < max) && (c != end) &&
1859: (c != end2) && (c != end3)) {
1.77 daniel 1860:
1.161 daniel 1861: if (c == 0) break;
1862: if (((c == '&') && (ctxt->token != '&')) && (NXT(1) == '#')) {
1.98 daniel 1863: int val = xmlParseCharRef(ctxt);
1.161 daniel 1864: COPY_BUF(0,buffer,nbchars,val);
1865: NEXTL(l);
1866: } else if ((c == '&') && (ctxt->token != '&') &&
1867: (what & XML_SUBSTITUTE_REF)) {
1.98 daniel 1868: ent = xmlParseEntityRef(ctxt);
1869: if ((ent != NULL) &&
1870: (ctxt->replaceEntities != 0)) {
1871: current = ent->content;
1872: while (*current != 0) {
1.161 daniel 1873: buffer[nbchars++] = *current++;
1874: if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.98 daniel 1875: growBuffer(buffer);
1.77 daniel 1876: }
1877: }
1.98 daniel 1878: } else if (ent != NULL) {
1.123 daniel 1879: const xmlChar *cur = ent->name;
1.98 daniel 1880:
1.161 daniel 1881: buffer[nbchars++] = '&';
1882: if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.98 daniel 1883: growBuffer(buffer);
1884: }
1.161 daniel 1885: while (*cur != 0) {
1886: buffer[nbchars++] = *cur++;
1887: }
1888: buffer[nbchars++] = ';';
1.77 daniel 1889: }
1.161 daniel 1890: } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
1.97 daniel 1891: /*
1.77 daniel 1892: * a PEReference induce to switch the entity flow,
1893: * we break here to flush the current set of chars
1894: * parsed if any. We will be called back later.
1.97 daniel 1895: */
1.91 daniel 1896: if (nbchars != 0) break;
1.77 daniel 1897:
1898: xmlParsePEReference(ctxt);
1.79 daniel 1899:
1.97 daniel 1900: /*
1.79 daniel 1901: * Pop-up of finished entities.
1.97 daniel 1902: */
1.152 daniel 1903: while ((RAW == 0) && (ctxt->inputNr > 1))
1.79 daniel 1904: xmlPopInput(ctxt);
1905:
1.98 daniel 1906: break;
1.77 daniel 1907: } else {
1.161 daniel 1908: COPY_BUF(l,buffer,nbchars,c);
1909: NEXTL(l);
1910: if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.86 daniel 1911: growBuffer(buffer);
1912: }
1.77 daniel 1913: }
1.161 daniel 1914: c = CUR_CHAR(l);
1.77 daniel 1915: }
1.161 daniel 1916: buffer[nbchars++] = 0;
1.77 daniel 1917: return(buffer);
1918: }
1919:
1.135 daniel 1920: /**
1921: * xmlStringDecodeEntities:
1922: * @ctxt: the parser context
1923: * @str: the input string
1924: * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1925: * @end: an end marker xmlChar, 0 if none
1926: * @end2: an end marker xmlChar, 0 if none
1927: * @end3: an end marker xmlChar, 0 if none
1928: *
1929: * [67] Reference ::= EntityRef | CharRef
1930: *
1931: * [69] PEReference ::= '%' Name ';'
1932: *
1933: * Returns A newly allocated string with the substitution done. The caller
1934: * must deallocate it !
1935: */
1936: xmlChar *
1937: xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
1938: xmlChar end, xmlChar end2, xmlChar end3) {
1939: xmlChar *buffer = NULL;
1940: int buffer_size = 0;
1941: xmlChar *out = NULL;
1942:
1943: xmlChar *current = NULL;
1944: xmlEntityPtr ent;
1945: xmlChar cur;
1946:
1947: /*
1948: * allocate a translation buffer.
1949: */
1.140 daniel 1950: buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
1.135 daniel 1951: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1952: if (buffer == NULL) {
1953: perror("xmlDecodeEntities: malloc failed");
1954: return(NULL);
1955: }
1956: out = buffer;
1957:
1958: /*
1959: * Ok loop until we reach one of the ending char or a size limit.
1960: */
1961: cur = *str;
1962: while ((cur != 0) && (cur != end) &&
1963: (cur != end2) && (cur != end3)) {
1964:
1965: if (cur == 0) break;
1966: if ((cur == '&') && (str[1] == '#')) {
1967: int val = xmlParseStringCharRef(ctxt, &str);
1968: if (val != 0)
1969: *out++ = val;
1970: } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
1971: ent = xmlParseStringEntityRef(ctxt, &str);
1972: if ((ent != NULL) &&
1973: (ctxt->replaceEntities != 0)) {
1974: current = ent->content;
1975: while (*current != 0) {
1976: *out++ = *current++;
1.140 daniel 1977: if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.135 daniel 1978: int index = out - buffer;
1979:
1980: growBuffer(buffer);
1981: out = &buffer[index];
1982: }
1983: }
1984: } else if (ent != NULL) {
1985: int i = xmlStrlen(ent->name);
1986: const xmlChar *cur = ent->name;
1987:
1988: *out++ = '&';
1.140 daniel 1989: if (out - buffer > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
1.135 daniel 1990: int index = out - buffer;
1991:
1992: growBuffer(buffer);
1993: out = &buffer[index];
1994: }
1995: for (;i > 0;i--)
1996: *out++ = *cur++;
1997: *out++ = ';';
1998: }
1999: } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2000: ent = xmlParseStringPEReference(ctxt, &str);
2001: if (ent != NULL) {
2002: current = ent->content;
2003: while (*current != 0) {
2004: *out++ = *current++;
1.140 daniel 2005: if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.135 daniel 2006: int index = out - buffer;
2007:
2008: growBuffer(buffer);
2009: out = &buffer[index];
2010: }
2011: }
2012: }
2013: } else {
1.156 daniel 2014: /* invalid for UTF-8 , use COPY(out); !!! */
1.135 daniel 2015: *out++ = cur;
1.140 daniel 2016: if (out - buffer > buffer_size - XML_PARSER_BUFFER_SIZE) {
1.135 daniel 2017: int index = out - buffer;
2018:
2019: growBuffer(buffer);
2020: out = &buffer[index];
2021: }
2022: str++;
2023: }
2024: cur = *str;
2025: }
2026: *out = 0;
2027: return(buffer);
2028: }
2029:
1.1 veillard 2030:
1.28 daniel 2031: /************************************************************************
2032: * *
1.75 daniel 2033: * Commodity functions to handle encodings *
2034: * *
2035: ************************************************************************/
2036:
2037: /**
2038: * xmlSwitchEncoding:
2039: * @ctxt: the parser context
1.124 daniel 2040: * @enc: the encoding value (number)
1.75 daniel 2041: *
2042: * change the input functions when discovering the character encoding
2043: * of a given entity.
2044: */
2045: void
2046: xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
2047: {
1.156 daniel 2048: xmlCharEncodingHandlerPtr handler;
2049:
2050: handler = xmlGetCharEncodingHandler(enc);
2051: if (handler != NULL) {
2052: if (ctxt->input != NULL) {
2053: if (ctxt->input->buf != NULL) {
2054: if (ctxt->input->buf->encoder != NULL) {
2055: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2056: ctxt->sax->error(ctxt->userData,
2057: "xmlSwitchEncoding : encoder already regitered\n");
2058: return;
2059: }
2060: ctxt->input->buf->encoder = handler;
2061:
2062: /*
2063: * Is there already some content down the pipe to convert
2064: */
2065: if ((ctxt->input->buf->buffer != NULL) &&
2066: (ctxt->input->buf->buffer->use > 0)) {
2067: xmlChar *buf;
2068: int res, len, size;
2069: int processed;
2070:
2071: /*
2072: * Specific handling of the Byte Order Mark for
2073: * UTF-16
2074: */
2075: if ((enc == XML_CHAR_ENCODING_UTF16LE) &&
2076: (ctxt->input->cur[0] == 0xFF) &&
2077: (ctxt->input->cur[1] == 0xFE)) {
2078: SKIP(2);
2079: }
2080: if ((enc == XML_CHAR_ENCODING_UTF16BE) &&
2081: (ctxt->input->cur[0] == 0xFE) &&
2082: (ctxt->input->cur[1] == 0xFF)) {
2083: SKIP(2);
2084: }
2085:
2086: /*
2087: * convert the non processed part
2088: */
2089: processed = ctxt->input->cur - ctxt->input->base;
2090: len = ctxt->input->buf->buffer->use - processed;
2091:
2092: if (len <= 0) {
2093: return;
2094: }
2095: size = ctxt->input->buf->buffer->use * 4;
2096: if (size < 4000)
2097: size = 4000;
1.167 daniel 2098: retry_larger:
1.160 daniel 2099: buf = (xmlChar *) xmlMalloc(size + 1);
1.156 daniel 2100: if (buf == NULL) {
2101: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2102: ctxt->sax->error(ctxt->userData,
2103: "xmlSwitchEncoding : out of memory\n");
2104: return;
2105: }
1.160 daniel 2106: /* TODO !!! Handling of buf too small */
1.156 daniel 2107: res = handler->input(buf, size, ctxt->input->cur, &len);
1.167 daniel 2108: if (res == -1) {
2109: size *= 2;
2110: xmlFree(buf);
2111: goto retry_larger;
2112: }
1.156 daniel 2113: if ((res < 0) ||
2114: (len != ctxt->input->buf->buffer->use - processed)) {
2115: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2116: ctxt->sax->error(ctxt->userData,
2117: "xmlSwitchEncoding : conversion failed\n");
2118: xmlFree(buf);
2119: return;
2120: }
1.167 daniel 2121:
1.156 daniel 2122: /*
2123: * Conversion succeeded, get rid of the old buffer
2124: */
2125: xmlFree(ctxt->input->buf->buffer->content);
2126: ctxt->input->buf->buffer->content = buf;
2127: ctxt->input->base = buf;
2128: ctxt->input->cur = buf;
2129: ctxt->input->buf->buffer->size = size;
2130: ctxt->input->buf->buffer->use = res;
1.160 daniel 2131: buf[res] = 0;
1.156 daniel 2132: }
2133: return;
2134: } else {
2135: if (ctxt->input->length == 0) {
2136: /*
2137: * When parsing a static memory array one must know the
2138: * size to be able to convert the buffer.
2139: */
2140: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2141: ctxt->sax->error(ctxt->userData,
2142: "xmlSwitchEncoding : no input\n");
2143: return;
2144: } else {
2145: xmlChar *buf;
2146: int res, len;
2147: int processed = ctxt->input->cur - ctxt->input->base;
2148:
2149: /*
2150: * convert the non processed part
2151: */
2152: len = ctxt->input->length - processed;
2153: if (len <= 0) {
2154: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2155: ctxt->sax->error(ctxt->userData,
2156: "xmlSwitchEncoding : input fully consumed?\n");
2157: return;
2158: }
2159: buf = (xmlChar *) xmlMalloc(ctxt->input->length * 4);
2160: if (buf == NULL) {
2161: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2162: ctxt->sax->error(ctxt->userData,
2163: "xmlSwitchEncoding : out of memory\n");
2164: return;
2165: }
2166: res = handler->input(buf, ctxt->input->length * 4,
2167: ctxt->input->cur, &len);
2168: if ((res < 0) ||
2169: (len != ctxt->input->length - processed)) {
2170: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2171: ctxt->sax->error(ctxt->userData,
2172: "xmlSwitchEncoding : conversion failed\n");
2173: xmlFree(buf);
2174: return;
2175: }
2176: /*
2177: * Conversion succeeded, get rid of the old buffer
2178: */
2179: if ((ctxt->input->free != NULL) &&
2180: (ctxt->input->base != NULL))
2181: ctxt->input->free((xmlChar *) ctxt->input->base);
2182: ctxt->input->base = ctxt->input->cur = buf;
2183: ctxt->input->length = res;
2184: }
2185: }
2186: } else {
2187: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2188: ctxt->sax->error(ctxt->userData,
2189: "xmlSwitchEncoding : no input\n");
2190: }
2191: }
2192:
1.75 daniel 2193: switch (enc) {
2194: case XML_CHAR_ENCODING_ERROR:
1.123 daniel 2195: ctxt->errNo = XML_ERR_UNKNOWN_ENCODING;
1.75 daniel 2196: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2197: ctxt->sax->error(ctxt->userData, "encoding unknown\n");
2198: ctxt->wellFormed = 0;
2199: break;
2200: case XML_CHAR_ENCODING_NONE:
2201: /* let's assume it's UTF-8 without the XML decl */
2202: return;
2203: case XML_CHAR_ENCODING_UTF8:
2204: /* default encoding, no conversion should be needed */
2205: return;
2206: case XML_CHAR_ENCODING_UTF16LE:
1.123 daniel 2207: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2208: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2209: ctxt->sax->error(ctxt->userData,
2210: "char encoding UTF16 little endian not supported\n");
2211: break;
2212: case XML_CHAR_ENCODING_UTF16BE:
1.123 daniel 2213: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2214: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2215: ctxt->sax->error(ctxt->userData,
2216: "char encoding UTF16 big endian not supported\n");
2217: break;
2218: case XML_CHAR_ENCODING_UCS4LE:
1.123 daniel 2219: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2220: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2221: ctxt->sax->error(ctxt->userData,
2222: "char encoding USC4 little endian not supported\n");
2223: break;
2224: case XML_CHAR_ENCODING_UCS4BE:
1.123 daniel 2225: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2226: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2227: ctxt->sax->error(ctxt->userData,
2228: "char encoding USC4 big endian not supported\n");
2229: break;
2230: case XML_CHAR_ENCODING_EBCDIC:
1.123 daniel 2231: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2232: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2233: ctxt->sax->error(ctxt->userData,
2234: "char encoding EBCDIC not supported\n");
2235: break;
2236: case XML_CHAR_ENCODING_UCS4_2143:
1.123 daniel 2237: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2238: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2239: ctxt->sax->error(ctxt->userData,
2240: "char encoding UCS4 2143 not supported\n");
2241: break;
2242: case XML_CHAR_ENCODING_UCS4_3412:
1.123 daniel 2243: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2244: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2245: ctxt->sax->error(ctxt->userData,
2246: "char encoding UCS4 3412 not supported\n");
2247: break;
2248: case XML_CHAR_ENCODING_UCS2:
1.123 daniel 2249: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2250: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2251: ctxt->sax->error(ctxt->userData,
2252: "char encoding UCS2 not supported\n");
2253: break;
2254: case XML_CHAR_ENCODING_8859_1:
1.123 daniel 2255: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2256: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2257: ctxt->sax->error(ctxt->userData,
2258: "char encoding ISO_8859_1 ISO Latin 1 not supported\n");
2259: break;
2260: case XML_CHAR_ENCODING_8859_2:
1.123 daniel 2261: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2262: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2263: ctxt->sax->error(ctxt->userData,
2264: "char encoding ISO_8859_2 ISO Latin 2 not supported\n");
2265: break;
2266: case XML_CHAR_ENCODING_8859_3:
1.123 daniel 2267: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2268: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2269: ctxt->sax->error(ctxt->userData,
2270: "char encoding ISO_8859_3 not supported\n");
2271: break;
2272: case XML_CHAR_ENCODING_8859_4:
1.123 daniel 2273: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2274: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2275: ctxt->sax->error(ctxt->userData,
2276: "char encoding ISO_8859_4 not supported\n");
2277: break;
2278: case XML_CHAR_ENCODING_8859_5:
1.123 daniel 2279: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2280: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2281: ctxt->sax->error(ctxt->userData,
2282: "char encoding ISO_8859_5 not supported\n");
2283: break;
2284: case XML_CHAR_ENCODING_8859_6:
1.123 daniel 2285: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2286: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2287: ctxt->sax->error(ctxt->userData,
2288: "char encoding ISO_8859_6 not supported\n");
2289: break;
2290: case XML_CHAR_ENCODING_8859_7:
1.123 daniel 2291: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2292: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2293: ctxt->sax->error(ctxt->userData,
2294: "char encoding ISO_8859_7 not supported\n");
2295: break;
2296: case XML_CHAR_ENCODING_8859_8:
1.123 daniel 2297: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2298: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2299: ctxt->sax->error(ctxt->userData,
2300: "char encoding ISO_8859_8 not supported\n");
2301: break;
2302: case XML_CHAR_ENCODING_8859_9:
1.123 daniel 2303: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2304: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2305: ctxt->sax->error(ctxt->userData,
2306: "char encoding ISO_8859_9 not supported\n");
2307: break;
2308: case XML_CHAR_ENCODING_2022_JP:
1.123 daniel 2309: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2310: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2311: ctxt->sax->error(ctxt->userData,
2312: "char encoding ISO-2022-JPnot supported\n");
2313: break;
2314: case XML_CHAR_ENCODING_SHIFT_JIS:
1.123 daniel 2315: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2316: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2317: ctxt->sax->error(ctxt->userData,
2318: "char encoding Shift_JISnot supported\n");
2319: break;
2320: case XML_CHAR_ENCODING_EUC_JP:
1.123 daniel 2321: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 2322: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2323: ctxt->sax->error(ctxt->userData,
2324: "char encoding EUC-JPnot supported\n");
2325: break;
2326: }
2327: }
2328:
2329: /************************************************************************
2330: * *
1.123 daniel 2331: * Commodity functions to handle xmlChars *
1.28 daniel 2332: * *
2333: ************************************************************************/
2334:
1.50 daniel 2335: /**
2336: * xmlStrndup:
1.123 daniel 2337: * @cur: the input xmlChar *
1.50 daniel 2338: * @len: the len of @cur
2339: *
1.123 daniel 2340: * a strndup for array of xmlChar's
1.68 daniel 2341: *
1.123 daniel 2342: * Returns a new xmlChar * or NULL
1.1 veillard 2343: */
1.123 daniel 2344: xmlChar *
2345: xmlStrndup(const xmlChar *cur, int len) {
1.135 daniel 2346: xmlChar *ret;
2347:
2348: if ((cur == NULL) || (len < 0)) return(NULL);
2349: ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.1 veillard 2350: if (ret == NULL) {
1.86 daniel 2351: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 2352: (len + 1) * (long)sizeof(xmlChar));
1.1 veillard 2353: return(NULL);
2354: }
1.123 daniel 2355: memcpy(ret, cur, len * sizeof(xmlChar));
1.1 veillard 2356: ret[len] = 0;
2357: return(ret);
2358: }
2359:
1.50 daniel 2360: /**
2361: * xmlStrdup:
1.123 daniel 2362: * @cur: the input xmlChar *
1.50 daniel 2363: *
1.152 daniel 2364: * a strdup for array of xmlChar's. Since they are supposed to be
2365: * encoded in UTF-8 or an encoding with 8bit based chars, we assume
2366: * a termination mark of '0'.
1.68 daniel 2367: *
1.123 daniel 2368: * Returns a new xmlChar * or NULL
1.1 veillard 2369: */
1.123 daniel 2370: xmlChar *
2371: xmlStrdup(const xmlChar *cur) {
2372: const xmlChar *p = cur;
1.1 veillard 2373:
1.135 daniel 2374: if (cur == NULL) return(NULL);
1.152 daniel 2375: while (*p != 0) p++;
1.1 veillard 2376: return(xmlStrndup(cur, p - cur));
2377: }
2378:
1.50 daniel 2379: /**
2380: * xmlCharStrndup:
2381: * @cur: the input char *
2382: * @len: the len of @cur
2383: *
1.123 daniel 2384: * a strndup for char's to xmlChar's
1.68 daniel 2385: *
1.123 daniel 2386: * Returns a new xmlChar * or NULL
1.45 daniel 2387: */
2388:
1.123 daniel 2389: xmlChar *
1.55 daniel 2390: xmlCharStrndup(const char *cur, int len) {
1.45 daniel 2391: int i;
1.135 daniel 2392: xmlChar *ret;
2393:
2394: if ((cur == NULL) || (len < 0)) return(NULL);
2395: ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.45 daniel 2396: if (ret == NULL) {
1.86 daniel 2397: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 2398: (len + 1) * (long)sizeof(xmlChar));
1.45 daniel 2399: return(NULL);
2400: }
2401: for (i = 0;i < len;i++)
1.123 daniel 2402: ret[i] = (xmlChar) cur[i];
1.45 daniel 2403: ret[len] = 0;
2404: return(ret);
2405: }
2406:
1.50 daniel 2407: /**
2408: * xmlCharStrdup:
2409: * @cur: the input char *
2410: * @len: the len of @cur
2411: *
1.123 daniel 2412: * a strdup for char's to xmlChar's
1.68 daniel 2413: *
1.123 daniel 2414: * Returns a new xmlChar * or NULL
1.45 daniel 2415: */
2416:
1.123 daniel 2417: xmlChar *
1.55 daniel 2418: xmlCharStrdup(const char *cur) {
1.45 daniel 2419: const char *p = cur;
2420:
1.135 daniel 2421: if (cur == NULL) return(NULL);
1.45 daniel 2422: while (*p != '\0') p++;
2423: return(xmlCharStrndup(cur, p - cur));
2424: }
2425:
1.50 daniel 2426: /**
2427: * xmlStrcmp:
1.123 daniel 2428: * @str1: the first xmlChar *
2429: * @str2: the second xmlChar *
1.50 daniel 2430: *
1.123 daniel 2431: * a strcmp for xmlChar's
1.68 daniel 2432: *
2433: * Returns the integer result of the comparison
1.14 veillard 2434: */
2435:
1.55 daniel 2436: int
1.123 daniel 2437: xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
1.14 veillard 2438: register int tmp;
2439:
1.135 daniel 2440: if ((str1 == NULL) && (str2 == NULL)) return(0);
2441: if (str1 == NULL) return(-1);
2442: if (str2 == NULL) return(1);
1.14 veillard 2443: do {
2444: tmp = *str1++ - *str2++;
2445: if (tmp != 0) return(tmp);
2446: } while ((*str1 != 0) && (*str2 != 0));
2447: return (*str1 - *str2);
2448: }
2449:
1.50 daniel 2450: /**
2451: * xmlStrncmp:
1.123 daniel 2452: * @str1: the first xmlChar *
2453: * @str2: the second xmlChar *
1.50 daniel 2454: * @len: the max comparison length
2455: *
1.123 daniel 2456: * a strncmp for xmlChar's
1.68 daniel 2457: *
2458: * Returns the integer result of the comparison
1.14 veillard 2459: */
2460:
1.55 daniel 2461: int
1.123 daniel 2462: xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
1.14 veillard 2463: register int tmp;
2464:
2465: if (len <= 0) return(0);
1.135 daniel 2466: if ((str1 == NULL) && (str2 == NULL)) return(0);
2467: if (str1 == NULL) return(-1);
2468: if (str2 == NULL) return(1);
1.14 veillard 2469: do {
2470: tmp = *str1++ - *str2++;
2471: if (tmp != 0) return(tmp);
2472: len--;
2473: if (len <= 0) return(0);
2474: } while ((*str1 != 0) && (*str2 != 0));
2475: return (*str1 - *str2);
2476: }
2477:
1.50 daniel 2478: /**
2479: * xmlStrchr:
1.123 daniel 2480: * @str: the xmlChar * array
2481: * @val: the xmlChar to search
1.50 daniel 2482: *
1.123 daniel 2483: * a strchr for xmlChar's
1.68 daniel 2484: *
1.123 daniel 2485: * Returns the xmlChar * for the first occurence or NULL.
1.14 veillard 2486: */
2487:
1.123 daniel 2488: const xmlChar *
2489: xmlStrchr(const xmlChar *str, xmlChar val) {
1.135 daniel 2490: if (str == NULL) return(NULL);
1.14 veillard 2491: while (*str != 0) {
1.123 daniel 2492: if (*str == val) return((xmlChar *) str);
1.14 veillard 2493: str++;
2494: }
2495: return(NULL);
1.89 daniel 2496: }
2497:
2498: /**
2499: * xmlStrstr:
1.123 daniel 2500: * @str: the xmlChar * array (haystack)
2501: * @val: the xmlChar to search (needle)
1.89 daniel 2502: *
1.123 daniel 2503: * a strstr for xmlChar's
1.89 daniel 2504: *
1.123 daniel 2505: * Returns the xmlChar * for the first occurence or NULL.
1.89 daniel 2506: */
2507:
1.123 daniel 2508: const xmlChar *
2509: xmlStrstr(const xmlChar *str, xmlChar *val) {
1.89 daniel 2510: int n;
2511:
2512: if (str == NULL) return(NULL);
2513: if (val == NULL) return(NULL);
2514: n = xmlStrlen(val);
2515:
2516: if (n == 0) return(str);
2517: while (*str != 0) {
2518: if (*str == *val) {
1.123 daniel 2519: if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
1.89 daniel 2520: }
2521: str++;
2522: }
2523: return(NULL);
2524: }
2525:
2526: /**
2527: * xmlStrsub:
1.123 daniel 2528: * @str: the xmlChar * array (haystack)
1.89 daniel 2529: * @start: the index of the first char (zero based)
2530: * @len: the length of the substring
2531: *
2532: * Extract a substring of a given string
2533: *
1.123 daniel 2534: * Returns the xmlChar * for the first occurence or NULL.
1.89 daniel 2535: */
2536:
1.123 daniel 2537: xmlChar *
2538: xmlStrsub(const xmlChar *str, int start, int len) {
1.89 daniel 2539: int i;
2540:
2541: if (str == NULL) return(NULL);
2542: if (start < 0) return(NULL);
1.90 daniel 2543: if (len < 0) return(NULL);
1.89 daniel 2544:
2545: for (i = 0;i < start;i++) {
2546: if (*str == 0) return(NULL);
2547: str++;
2548: }
2549: if (*str == 0) return(NULL);
2550: return(xmlStrndup(str, len));
1.14 veillard 2551: }
1.28 daniel 2552:
1.50 daniel 2553: /**
2554: * xmlStrlen:
1.123 daniel 2555: * @str: the xmlChar * array
1.50 daniel 2556: *
1.127 daniel 2557: * length of a xmlChar's string
1.68 daniel 2558: *
1.123 daniel 2559: * Returns the number of xmlChar contained in the ARRAY.
1.45 daniel 2560: */
2561:
1.55 daniel 2562: int
1.123 daniel 2563: xmlStrlen(const xmlChar *str) {
1.45 daniel 2564: int len = 0;
2565:
2566: if (str == NULL) return(0);
2567: while (*str != 0) {
2568: str++;
2569: len++;
2570: }
2571: return(len);
2572: }
2573:
1.50 daniel 2574: /**
2575: * xmlStrncat:
1.123 daniel 2576: * @cur: the original xmlChar * array
2577: * @add: the xmlChar * array added
1.50 daniel 2578: * @len: the length of @add
2579: *
1.123 daniel 2580: * a strncat for array of xmlChar's
1.68 daniel 2581: *
1.123 daniel 2582: * Returns a new xmlChar * containing the concatenated string.
1.45 daniel 2583: */
2584:
1.123 daniel 2585: xmlChar *
2586: xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
1.45 daniel 2587: int size;
1.123 daniel 2588: xmlChar *ret;
1.45 daniel 2589:
2590: if ((add == NULL) || (len == 0))
2591: return(cur);
2592: if (cur == NULL)
2593: return(xmlStrndup(add, len));
2594:
2595: size = xmlStrlen(cur);
1.123 daniel 2596: ret = xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
1.45 daniel 2597: if (ret == NULL) {
1.86 daniel 2598: fprintf(stderr, "xmlStrncat: realloc of %ld byte failed\n",
1.123 daniel 2599: (size + len + 1) * (long)sizeof(xmlChar));
1.45 daniel 2600: return(cur);
2601: }
1.123 daniel 2602: memcpy(&ret[size], add, len * sizeof(xmlChar));
1.45 daniel 2603: ret[size + len] = 0;
2604: return(ret);
2605: }
2606:
1.50 daniel 2607: /**
2608: * xmlStrcat:
1.123 daniel 2609: * @cur: the original xmlChar * array
2610: * @add: the xmlChar * array added
1.50 daniel 2611: *
1.152 daniel 2612: * a strcat for array of xmlChar's. Since they are supposed to be
2613: * encoded in UTF-8 or an encoding with 8bit based chars, we assume
2614: * a termination mark of '0'.
1.68 daniel 2615: *
1.123 daniel 2616: * Returns a new xmlChar * containing the concatenated string.
1.45 daniel 2617: */
1.123 daniel 2618: xmlChar *
2619: xmlStrcat(xmlChar *cur, const xmlChar *add) {
2620: const xmlChar *p = add;
1.45 daniel 2621:
2622: if (add == NULL) return(cur);
2623: if (cur == NULL)
2624: return(xmlStrdup(add));
2625:
1.152 daniel 2626: while (*p != 0) p++;
1.45 daniel 2627: return(xmlStrncat(cur, add, p - add));
2628: }
2629:
2630: /************************************************************************
2631: * *
2632: * Commodity functions, cleanup needed ? *
2633: * *
2634: ************************************************************************/
2635:
1.50 daniel 2636: /**
2637: * areBlanks:
2638: * @ctxt: an XML parser context
1.123 daniel 2639: * @str: a xmlChar *
1.50 daniel 2640: * @len: the size of @str
2641: *
1.45 daniel 2642: * Is this a sequence of blank chars that one can ignore ?
1.50 daniel 2643: *
1.68 daniel 2644: * Returns 1 if ignorable 0 otherwise.
1.45 daniel 2645: */
2646:
1.123 daniel 2647: static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1.104 daniel 2648: int i, ret;
1.45 daniel 2649: xmlNodePtr lastChild;
2650:
2651: for (i = 0;i < len;i++)
2652: if (!(IS_BLANK(str[i]))) return(0);
2653:
1.152 daniel 2654: if (RAW != '<') return(0);
1.72 daniel 2655: if (ctxt->node == NULL) return(0);
1.104 daniel 2656: if (ctxt->myDoc != NULL) {
2657: ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2658: if (ret == 0) return(1);
2659: if (ret == 1) return(0);
2660: }
2661: /*
2662: * heuristic
2663: */
1.45 daniel 2664: lastChild = xmlGetLastChild(ctxt->node);
2665: if (lastChild == NULL) {
2666: if (ctxt->node->content != NULL) return(0);
2667: } else if (xmlNodeIsText(lastChild))
2668: return(0);
1.157 daniel 2669: else if ((ctxt->node->children != NULL) &&
2670: (xmlNodeIsText(ctxt->node->children)))
1.104 daniel 2671: return(0);
1.45 daniel 2672: return(1);
2673: }
2674:
1.50 daniel 2675: /**
2676: * xmlHandleEntity:
2677: * @ctxt: an XML parser context
2678: * @entity: an XML entity pointer.
2679: *
2680: * Default handling of defined entities, when should we define a new input
1.45 daniel 2681: * stream ? When do we just handle that as a set of chars ?
1.99 daniel 2682: *
2683: * OBSOLETE: to be removed at some point.
1.45 daniel 2684: */
2685:
1.55 daniel 2686: void
2687: xmlHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45 daniel 2688: int len;
1.50 daniel 2689: xmlParserInputPtr input;
1.45 daniel 2690:
2691: if (entity->content == NULL) {
1.123 daniel 2692: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55 daniel 2693: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2694: ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
1.45 daniel 2695: entity->name);
1.59 daniel 2696: ctxt->wellFormed = 0;
1.45 daniel 2697: return;
2698: }
2699: len = xmlStrlen(entity->content);
2700: if (len <= 2) goto handle_as_char;
2701:
2702: /*
2703: * Redefine its content as an input stream.
2704: */
1.50 daniel 2705: input = xmlNewEntityInputStream(ctxt, entity);
2706: xmlPushInput(ctxt, input);
1.45 daniel 2707: return;
2708:
2709: handle_as_char:
2710: /*
2711: * Just handle the content as a set of chars.
2712: */
1.72 daniel 2713: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
1.74 daniel 2714: ctxt->sax->characters(ctxt->userData, entity->content, len);
1.45 daniel 2715:
2716: }
2717:
2718: /*
2719: * Forward definition for recusive behaviour.
2720: */
1.77 daniel 2721: void xmlParsePEReference(xmlParserCtxtPtr ctxt);
2722: void xmlParseReference(xmlParserCtxtPtr ctxt);
1.45 daniel 2723:
1.28 daniel 2724: /************************************************************************
2725: * *
2726: * Extra stuff for namespace support *
2727: * Relates to http://www.w3.org/TR/WD-xml-names *
2728: * *
2729: ************************************************************************/
2730:
1.50 daniel 2731: /**
2732: * xmlNamespaceParseNCName:
2733: * @ctxt: an XML parser context
2734: *
2735: * parse an XML namespace name.
1.28 daniel 2736: *
2737: * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
2738: *
2739: * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
2740: * CombiningChar | Extender
1.68 daniel 2741: *
2742: * Returns the namespace name or NULL
1.28 daniel 2743: */
2744:
1.123 daniel 2745: xmlChar *
1.55 daniel 2746: xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
1.152 daniel 2747: xmlChar buf[XML_MAX_NAMELEN + 5];
2748: int len = 0, l;
2749: int cur = CUR_CHAR(l);
1.28 daniel 2750:
1.156 daniel 2751: /* load first the value of the char !!! */
1.152 daniel 2752: if (!IS_LETTER(cur) && (cur != '_')) return(NULL);
1.28 daniel 2753:
1.152 daniel 2754: while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2755: (cur == '.') || (cur == '-') ||
2756: (cur == '_') ||
2757: (IS_COMBINING(cur)) ||
2758: (IS_EXTENDER(cur))) {
2759: COPY_BUF(l,buf,len,cur);
2760: NEXTL(l);
2761: cur = CUR_CHAR(l);
1.91 daniel 2762: if (len >= XML_MAX_NAMELEN) {
2763: fprintf(stderr,
2764: "xmlNamespaceParseNCName: reached XML_MAX_NAMELEN limit\n");
1.152 daniel 2765: while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2766: (cur == '.') || (cur == '-') ||
2767: (cur == '_') ||
2768: (IS_COMBINING(cur)) ||
2769: (IS_EXTENDER(cur))) {
2770: NEXTL(l);
2771: cur = CUR_CHAR(l);
2772: }
1.91 daniel 2773: break;
2774: }
2775: }
2776: return(xmlStrndup(buf, len));
1.28 daniel 2777: }
2778:
1.50 daniel 2779: /**
2780: * xmlNamespaceParseQName:
2781: * @ctxt: an XML parser context
1.123 daniel 2782: * @prefix: a xmlChar **
1.50 daniel 2783: *
2784: * parse an XML qualified name
1.28 daniel 2785: *
2786: * [NS 5] QName ::= (Prefix ':')? LocalPart
2787: *
2788: * [NS 6] Prefix ::= NCName
2789: *
2790: * [NS 7] LocalPart ::= NCName
1.68 daniel 2791: *
1.127 daniel 2792: * Returns the local part, and prefix is updated
1.50 daniel 2793: * to get the Prefix if any.
1.28 daniel 2794: */
2795:
1.123 daniel 2796: xmlChar *
2797: xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, xmlChar **prefix) {
2798: xmlChar *ret = NULL;
1.28 daniel 2799:
2800: *prefix = NULL;
2801: ret = xmlNamespaceParseNCName(ctxt);
1.152 daniel 2802: if (RAW == ':') {
1.28 daniel 2803: *prefix = ret;
1.40 daniel 2804: NEXT;
1.28 daniel 2805: ret = xmlNamespaceParseNCName(ctxt);
2806: }
2807:
2808: return(ret);
2809: }
2810:
1.50 daniel 2811: /**
1.72 daniel 2812: * xmlSplitQName:
1.162 daniel 2813: * @ctxt: an XML parser context
1.72 daniel 2814: * @name: an XML parser context
1.123 daniel 2815: * @prefix: a xmlChar **
1.72 daniel 2816: *
2817: * parse an XML qualified name string
2818: *
2819: * [NS 5] QName ::= (Prefix ':')? LocalPart
2820: *
2821: * [NS 6] Prefix ::= NCName
2822: *
2823: * [NS 7] LocalPart ::= NCName
2824: *
1.127 daniel 2825: * Returns the local part, and prefix is updated
1.72 daniel 2826: * to get the Prefix if any.
2827: */
2828:
1.123 daniel 2829: xmlChar *
1.162 daniel 2830: xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2831: xmlChar buf[XML_MAX_NAMELEN + 5];
2832: int len = 0;
1.123 daniel 2833: xmlChar *ret = NULL;
2834: const xmlChar *cur = name;
1.162 daniel 2835: int c,l;
1.72 daniel 2836:
2837: *prefix = NULL;
1.113 daniel 2838:
2839: /* xml: prefix is not really a namespace */
2840: if ((cur[0] == 'x') && (cur[1] == 'm') &&
2841: (cur[2] == 'l') && (cur[3] == ':'))
2842: return(xmlStrdup(name));
2843:
1.162 daniel 2844: /* nasty but valid */
2845: if (cur[0] == ':')
2846: return(xmlStrdup(name));
2847:
2848: c = CUR_SCHAR(cur, l);
2849: if (!IS_LETTER(c) && (c != '_')) return(NULL);
1.72 daniel 2850:
1.162 daniel 2851: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2852: (c == '.') || (c == '-') ||
2853: (c == '_') ||
2854: (IS_COMBINING(c)) ||
2855: (IS_EXTENDER(c))) {
2856: COPY_BUF(l,buf,len,c);
2857: cur += l;
2858: c = CUR_SCHAR(cur, l);
2859: }
1.72 daniel 2860:
1.162 daniel 2861: ret = xmlStrndup(buf, len);
1.72 daniel 2862:
1.162 daniel 2863: if (c == ':') {
2864: cur += l;
1.163 daniel 2865: c = CUR_SCHAR(cur, l);
1.162 daniel 2866: if (!IS_LETTER(c) && (c != '_')) return(ret);
1.72 daniel 2867: *prefix = ret;
1.162 daniel 2868: len = 0;
1.72 daniel 2869:
1.162 daniel 2870: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2871: (c == '.') || (c == '-') ||
2872: (c == '_') ||
2873: (IS_COMBINING(c)) ||
2874: (IS_EXTENDER(c))) {
2875: COPY_BUF(l,buf,len,c);
2876: cur += l;
2877: c = CUR_SCHAR(cur, l);
2878: }
1.72 daniel 2879:
1.162 daniel 2880: ret = xmlStrndup(buf, len);
1.72 daniel 2881: }
2882:
2883: return(ret);
2884: }
2885: /**
1.50 daniel 2886: * xmlNamespaceParseNSDef:
2887: * @ctxt: an XML parser context
2888: *
2889: * parse a namespace prefix declaration
1.28 daniel 2890: *
2891: * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral
2892: *
2893: * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)?
1.68 daniel 2894: *
2895: * Returns the namespace name
1.28 daniel 2896: */
2897:
1.123 daniel 2898: xmlChar *
1.55 daniel 2899: xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) {
1.123 daniel 2900: xmlChar *name = NULL;
1.28 daniel 2901:
1.152 daniel 2902: if ((RAW == 'x') && (NXT(1) == 'm') &&
1.40 daniel 2903: (NXT(2) == 'l') && (NXT(3) == 'n') &&
2904: (NXT(4) == 's')) {
2905: SKIP(5);
1.152 daniel 2906: if (RAW == ':') {
1.40 daniel 2907: NEXT;
1.28 daniel 2908: name = xmlNamespaceParseNCName(ctxt);
2909: }
2910: }
1.39 daniel 2911: return(name);
1.28 daniel 2912: }
2913:
1.50 daniel 2914: /**
2915: * xmlParseQuotedString:
2916: * @ctxt: an XML parser context
2917: *
1.45 daniel 2918: * [OLD] Parse and return a string between quotes or doublequotes
1.110 daniel 2919: * To be removed at next drop of binary compatibility
1.68 daniel 2920: *
2921: * Returns the string parser or NULL.
1.45 daniel 2922: */
1.123 daniel 2923: xmlChar *
1.55 daniel 2924: xmlParseQuotedString(xmlParserCtxtPtr ctxt) {
1.135 daniel 2925: xmlChar *buf = NULL;
1.152 daniel 2926: int len = 0,l;
1.140 daniel 2927: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 2928: int c;
1.45 daniel 2929:
1.135 daniel 2930: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2931: if (buf == NULL) {
2932: fprintf(stderr, "malloc of %d byte failed\n", size);
2933: return(NULL);
2934: }
1.152 daniel 2935: if (RAW == '"') {
1.45 daniel 2936: NEXT;
1.152 daniel 2937: c = CUR_CHAR(l);
1.135 daniel 2938: while (IS_CHAR(c) && (c != '"')) {
1.152 daniel 2939: if (len + 5 >= size) {
1.135 daniel 2940: size *= 2;
2941: buf = xmlRealloc(buf, size * sizeof(xmlChar));
2942: if (buf == NULL) {
2943: fprintf(stderr, "realloc of %d byte failed\n", size);
2944: return(NULL);
2945: }
2946: }
1.152 daniel 2947: COPY_BUF(l,buf,len,c);
2948: NEXTL(l);
2949: c = CUR_CHAR(l);
1.135 daniel 2950: }
2951: if (c != '"') {
1.123 daniel 2952: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 2953: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.135 daniel 2954: ctxt->sax->error(ctxt->userData,
2955: "String not closed \"%.50s\"\n", buf);
1.59 daniel 2956: ctxt->wellFormed = 0;
1.55 daniel 2957: } else {
1.45 daniel 2958: NEXT;
2959: }
1.152 daniel 2960: } else if (RAW == '\''){
1.45 daniel 2961: NEXT;
1.135 daniel 2962: c = CUR;
2963: while (IS_CHAR(c) && (c != '\'')) {
2964: if (len + 1 >= size) {
2965: size *= 2;
2966: buf = xmlRealloc(buf, size * sizeof(xmlChar));
2967: if (buf == NULL) {
2968: fprintf(stderr, "realloc of %d byte failed\n", size);
2969: return(NULL);
2970: }
2971: }
2972: buf[len++] = c;
2973: NEXT;
2974: c = CUR;
2975: }
1.152 daniel 2976: if (RAW != '\'') {
1.123 daniel 2977: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 2978: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.135 daniel 2979: ctxt->sax->error(ctxt->userData,
2980: "String not closed \"%.50s\"\n", buf);
1.59 daniel 2981: ctxt->wellFormed = 0;
1.55 daniel 2982: } else {
1.45 daniel 2983: NEXT;
2984: }
2985: }
1.135 daniel 2986: return(buf);
1.45 daniel 2987: }
2988:
1.50 daniel 2989: /**
2990: * xmlParseNamespace:
2991: * @ctxt: an XML parser context
2992: *
1.45 daniel 2993: * [OLD] xmlParseNamespace: parse specific PI '<?namespace ...' constructs.
2994: *
2995: * This is what the older xml-name Working Draft specified, a bunch of
2996: * other stuff may still rely on it, so support is still here as
1.127 daniel 2997: * if it was declared on the root of the Tree:-(
1.110 daniel 2998: *
2999: * To be removed at next drop of binary compatibility
1.45 daniel 3000: */
3001:
1.55 daniel 3002: void
3003: xmlParseNamespace(xmlParserCtxtPtr ctxt) {
1.123 daniel 3004: xmlChar *href = NULL;
3005: xmlChar *prefix = NULL;
1.45 daniel 3006: int garbage = 0;
3007:
3008: /*
3009: * We just skipped "namespace" or "xml:namespace"
3010: */
3011: SKIP_BLANKS;
3012:
1.153 daniel 3013: while (IS_CHAR(RAW) && (RAW != '>')) {
1.45 daniel 3014: /*
3015: * We can have "ns" or "prefix" attributes
3016: * Old encoding as 'href' or 'AS' attributes is still supported
3017: */
1.152 daniel 3018: if ((RAW == 'n') && (NXT(1) == 's')) {
1.45 daniel 3019: garbage = 0;
3020: SKIP(2);
3021: SKIP_BLANKS;
3022:
1.152 daniel 3023: if (RAW != '=') continue;
1.45 daniel 3024: NEXT;
3025: SKIP_BLANKS;
3026:
3027: href = xmlParseQuotedString(ctxt);
3028: SKIP_BLANKS;
1.152 daniel 3029: } else if ((RAW == 'h') && (NXT(1) == 'r') &&
1.45 daniel 3030: (NXT(2) == 'e') && (NXT(3) == 'f')) {
3031: garbage = 0;
3032: SKIP(4);
3033: SKIP_BLANKS;
3034:
1.152 daniel 3035: if (RAW != '=') continue;
1.45 daniel 3036: NEXT;
3037: SKIP_BLANKS;
3038:
3039: href = xmlParseQuotedString(ctxt);
3040: SKIP_BLANKS;
1.152 daniel 3041: } else if ((RAW == 'p') && (NXT(1) == 'r') &&
1.45 daniel 3042: (NXT(2) == 'e') && (NXT(3) == 'f') &&
3043: (NXT(4) == 'i') && (NXT(5) == 'x')) {
3044: garbage = 0;
3045: SKIP(6);
3046: SKIP_BLANKS;
3047:
1.152 daniel 3048: if (RAW != '=') continue;
1.45 daniel 3049: NEXT;
3050: SKIP_BLANKS;
3051:
3052: prefix = xmlParseQuotedString(ctxt);
3053: SKIP_BLANKS;
1.152 daniel 3054: } else if ((RAW == 'A') && (NXT(1) == 'S')) {
1.45 daniel 3055: garbage = 0;
3056: SKIP(2);
3057: SKIP_BLANKS;
3058:
1.152 daniel 3059: if (RAW != '=') continue;
1.45 daniel 3060: NEXT;
3061: SKIP_BLANKS;
3062:
3063: prefix = xmlParseQuotedString(ctxt);
3064: SKIP_BLANKS;
1.152 daniel 3065: } else if ((RAW == '?') && (NXT(1) == '>')) {
1.45 daniel 3066: garbage = 0;
1.91 daniel 3067: NEXT;
1.45 daniel 3068: } else {
3069: /*
3070: * Found garbage when parsing the namespace
3071: */
1.122 daniel 3072: if (!garbage) {
1.55 daniel 3073: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3074: ctxt->sax->error(ctxt->userData,
3075: "xmlParseNamespace found garbage\n");
3076: }
1.123 daniel 3077: ctxt->errNo = XML_ERR_NS_DECL_ERROR;
1.59 daniel 3078: ctxt->wellFormed = 0;
1.45 daniel 3079: NEXT;
3080: }
3081: }
3082:
3083: MOVETO_ENDTAG(CUR_PTR);
3084: NEXT;
3085:
3086: /*
3087: * Register the DTD.
1.72 daniel 3088: if (href != NULL)
3089: if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
1.74 daniel 3090: ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
1.45 daniel 3091: */
3092:
1.119 daniel 3093: if (prefix != NULL) xmlFree(prefix);
3094: if (href != NULL) xmlFree(href);
1.45 daniel 3095: }
3096:
1.28 daniel 3097: /************************************************************************
3098: * *
3099: * The parser itself *
3100: * Relates to http://www.w3.org/TR/REC-xml *
3101: * *
3102: ************************************************************************/
1.14 veillard 3103:
1.50 daniel 3104: /**
1.97 daniel 3105: * xmlScanName:
3106: * @ctxt: an XML parser context
3107: *
3108: * Trickery: parse an XML name but without consuming the input flow
3109: * Needed for rollback cases.
3110: *
3111: * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3112: * CombiningChar | Extender
3113: *
3114: * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3115: *
3116: * [6] Names ::= Name (S Name)*
3117: *
3118: * Returns the Name parsed or NULL
3119: */
3120:
1.123 daniel 3121: xmlChar *
1.97 daniel 3122: xmlScanName(xmlParserCtxtPtr ctxt) {
1.123 daniel 3123: xmlChar buf[XML_MAX_NAMELEN];
1.97 daniel 3124: int len = 0;
3125:
3126: GROW;
1.152 daniel 3127: if (!IS_LETTER(RAW) && (RAW != '_') &&
3128: (RAW != ':')) {
1.97 daniel 3129: return(NULL);
3130: }
3131:
3132: while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
3133: (NXT(len) == '.') || (NXT(len) == '-') ||
3134: (NXT(len) == '_') || (NXT(len) == ':') ||
3135: (IS_COMBINING(NXT(len))) ||
3136: (IS_EXTENDER(NXT(len)))) {
3137: buf[len] = NXT(len);
3138: len++;
3139: if (len >= XML_MAX_NAMELEN) {
3140: fprintf(stderr,
3141: "xmlScanName: reached XML_MAX_NAMELEN limit\n");
3142: while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
3143: (NXT(len) == '.') || (NXT(len) == '-') ||
3144: (NXT(len) == '_') || (NXT(len) == ':') ||
3145: (IS_COMBINING(NXT(len))) ||
3146: (IS_EXTENDER(NXT(len))))
3147: len++;
3148: break;
3149: }
3150: }
3151: return(xmlStrndup(buf, len));
3152: }
3153:
3154: /**
1.50 daniel 3155: * xmlParseName:
3156: * @ctxt: an XML parser context
3157: *
3158: * parse an XML name.
1.22 daniel 3159: *
3160: * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3161: * CombiningChar | Extender
3162: *
3163: * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3164: *
3165: * [6] Names ::= Name (S Name)*
1.68 daniel 3166: *
3167: * Returns the Name parsed or NULL
1.1 veillard 3168: */
3169:
1.123 daniel 3170: xmlChar *
1.55 daniel 3171: xmlParseName(xmlParserCtxtPtr ctxt) {
1.160 daniel 3172: xmlChar buf[XML_MAX_NAMELEN + 5];
3173: int len = 0, l;
3174: int c;
1.1 veillard 3175:
1.91 daniel 3176: GROW;
1.160 daniel 3177: c = CUR_CHAR(l);
3178: if (!IS_LETTER(c) && (c != '_') &&
3179: (c != ':')) {
1.91 daniel 3180: return(NULL);
3181: }
1.40 daniel 3182:
1.160 daniel 3183: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3184: (c == '.') || (c == '-') ||
3185: (c == '_') || (c == ':') ||
3186: (IS_COMBINING(c)) ||
3187: (IS_EXTENDER(c))) {
3188: COPY_BUF(l,buf,len,c);
3189: NEXTL(l);
3190: c = CUR_CHAR(l);
1.91 daniel 3191: if (len >= XML_MAX_NAMELEN) {
3192: fprintf(stderr,
3193: "xmlParseName: reached XML_MAX_NAMELEN limit\n");
1.160 daniel 3194: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3195: (c == '.') || (c == '-') ||
3196: (c == '_') || (c == ':') ||
3197: (IS_COMBINING(c)) ||
3198: (IS_EXTENDER(c))) {
3199: NEXTL(l);
3200: c = CUR_CHAR(l);
1.97 daniel 3201: }
1.91 daniel 3202: break;
3203: }
3204: }
3205: return(xmlStrndup(buf, len));
1.22 daniel 3206: }
3207:
1.50 daniel 3208: /**
1.135 daniel 3209: * xmlParseStringName:
3210: * @ctxt: an XML parser context
3211: * @str: a pointer to an index in the string
3212: *
3213: * parse an XML name.
3214: *
3215: * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3216: * CombiningChar | Extender
3217: *
3218: * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3219: *
3220: * [6] Names ::= Name (S Name)*
3221: *
3222: * Returns the Name parsed or NULL. The str pointer
3223: * is updated to the current location in the string.
3224: */
3225:
3226: xmlChar *
3227: xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3228: const xmlChar *ptr;
3229: const xmlChar *start;
3230: xmlChar cur;
3231:
3232: if ((str == NULL) || (*str == NULL)) return(NULL);
3233:
3234: start = ptr = *str;
3235: cur = *ptr;
3236: if (!IS_LETTER(cur) && (cur != '_') &&
3237: (cur != ':')) {
3238: return(NULL);
3239: }
3240:
3241: while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
3242: (cur == '.') || (cur == '-') ||
3243: (cur == '_') || (cur == ':') ||
3244: (IS_COMBINING(cur)) ||
3245: (IS_EXTENDER(cur))) {
3246: ptr++;
3247: cur = *ptr;
3248: }
3249: *str = ptr;
3250: return(xmlStrndup(start, ptr - start ));
3251: }
3252:
3253: /**
1.50 daniel 3254: * xmlParseNmtoken:
3255: * @ctxt: an XML parser context
3256: *
3257: * parse an XML Nmtoken.
1.22 daniel 3258: *
3259: * [7] Nmtoken ::= (NameChar)+
3260: *
3261: * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
1.68 daniel 3262: *
3263: * Returns the Nmtoken parsed or NULL
1.22 daniel 3264: */
3265:
1.123 daniel 3266: xmlChar *
1.55 daniel 3267: xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
1.123 daniel 3268: xmlChar buf[XML_MAX_NAMELEN];
1.91 daniel 3269: int len = 0;
1.160 daniel 3270: int c,l;
1.22 daniel 3271:
1.91 daniel 3272: GROW;
1.160 daniel 3273: c = CUR_CHAR(l);
3274: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3275: (c == '.') || (c == '-') ||
3276: (c == '_') || (c == ':') ||
3277: (IS_COMBINING(c)) ||
3278: (IS_EXTENDER(c))) {
3279: COPY_BUF(l,buf,len,c);
3280: NEXTL(l);
3281: c = CUR_CHAR(l);
1.91 daniel 3282: if (len >= XML_MAX_NAMELEN) {
3283: fprintf(stderr,
3284: "xmlParseNmtoken: reached XML_MAX_NAMELEN limit\n");
1.160 daniel 3285: while ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3286: (c == '.') || (c == '-') ||
3287: (c == '_') || (c == ':') ||
3288: (IS_COMBINING(c)) ||
3289: (IS_EXTENDER(c))) {
3290: NEXTL(l);
3291: c = CUR_CHAR(l);
3292: }
1.91 daniel 3293: break;
3294: }
3295: }
1.168 daniel 3296: if (len == 0)
3297: return(NULL);
1.91 daniel 3298: return(xmlStrndup(buf, len));
1.1 veillard 3299: }
3300:
1.50 daniel 3301: /**
3302: * xmlParseEntityValue:
3303: * @ctxt: an XML parser context
1.78 daniel 3304: * @orig: if non-NULL store a copy of the original entity value
1.50 daniel 3305: *
3306: * parse a value for ENTITY decl.
1.24 daniel 3307: *
3308: * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3309: * "'" ([^%&'] | PEReference | Reference)* "'"
1.68 daniel 3310: *
1.78 daniel 3311: * Returns the EntityValue parsed with reference substitued or NULL
1.24 daniel 3312: */
3313:
1.123 daniel 3314: xmlChar *
3315: xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
1.135 daniel 3316: xmlChar *buf = NULL;
3317: int len = 0;
1.140 daniel 3318: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 3319: int c, l;
1.135 daniel 3320: xmlChar stop;
1.123 daniel 3321: xmlChar *ret = NULL;
1.98 daniel 3322: xmlParserInputPtr input;
1.24 daniel 3323:
1.152 daniel 3324: if (RAW == '"') stop = '"';
3325: else if (RAW == '\'') stop = '\'';
1.135 daniel 3326: else {
3327: ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
3328: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3329: ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
3330: ctxt->wellFormed = 0;
3331: return(NULL);
3332: }
3333: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
3334: if (buf == NULL) {
3335: fprintf(stderr, "malloc of %d byte failed\n", size);
3336: return(NULL);
3337: }
1.94 daniel 3338:
1.135 daniel 3339: /*
3340: * The content of the entity definition is copied in a buffer.
3341: */
1.94 daniel 3342:
1.135 daniel 3343: ctxt->instate = XML_PARSER_ENTITY_VALUE;
3344: input = ctxt->input;
3345: GROW;
3346: NEXT;
1.152 daniel 3347: c = CUR_CHAR(l);
1.135 daniel 3348: /*
3349: * NOTE: 4.4.5 Included in Literal
3350: * When a parameter entity reference appears in a literal entity
3351: * value, ... a single or double quote character in the replacement
3352: * text is always treated as a normal data character and will not
3353: * terminate the literal.
3354: * In practice it means we stop the loop only when back at parsing
3355: * the initial entity and the quote is found
3356: */
3357: while (IS_CHAR(c) && ((c != stop) || (ctxt->input != input))) {
1.152 daniel 3358: if (len + 5 >= size) {
1.135 daniel 3359: size *= 2;
3360: buf = xmlRealloc(buf, size * sizeof(xmlChar));
3361: if (buf == NULL) {
3362: fprintf(stderr, "realloc of %d byte failed\n", size);
3363: return(NULL);
1.94 daniel 3364: }
1.79 daniel 3365: }
1.152 daniel 3366: COPY_BUF(l,buf,len,c);
3367: NEXTL(l);
1.98 daniel 3368: /*
1.135 daniel 3369: * Pop-up of finished entities.
1.98 daniel 3370: */
1.152 daniel 3371: while ((RAW == 0) && (ctxt->inputNr > 1))
1.135 daniel 3372: xmlPopInput(ctxt);
1.152 daniel 3373:
3374: c = CUR_CHAR(l);
1.135 daniel 3375: if (c == 0) {
1.94 daniel 3376: GROW;
1.152 daniel 3377: c = CUR_CHAR(l);
1.79 daniel 3378: }
1.135 daniel 3379: }
3380: buf[len] = 0;
3381:
3382: /*
3383: * Then PEReference entities are substituted.
3384: */
3385: if (c != stop) {
3386: ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.55 daniel 3387: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.135 daniel 3388: ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
1.59 daniel 3389: ctxt->wellFormed = 0;
1.170 ! daniel 3390: xmlFree(buf);
1.135 daniel 3391: } else {
3392: NEXT;
3393: /*
3394: * NOTE: 4.4.7 Bypassed
3395: * When a general entity reference appears in the EntityValue in
3396: * an entity declaration, it is bypassed and left as is.
3397: * so XML_SUBSTITUTE_REF is not set.
3398: */
3399: ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3400: 0, 0, 0);
3401: if (orig != NULL)
3402: *orig = buf;
3403: else
3404: xmlFree(buf);
1.24 daniel 3405: }
3406:
3407: return(ret);
3408: }
3409:
1.50 daniel 3410: /**
3411: * xmlParseAttValue:
3412: * @ctxt: an XML parser context
3413: *
3414: * parse a value for an attribute
1.78 daniel 3415: * Note: the parser won't do substitution of entities here, this
1.113 daniel 3416: * will be handled later in xmlStringGetNodeList
1.29 daniel 3417: *
3418: * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
3419: * "'" ([^<&'] | Reference)* "'"
1.68 daniel 3420: *
1.129 daniel 3421: * 3.3.3 Attribute-Value Normalization:
3422: * Before the value of an attribute is passed to the application or
3423: * checked for validity, the XML processor must normalize it as follows:
3424: * - a character reference is processed by appending the referenced
3425: * character to the attribute value
3426: * - an entity reference is processed by recursively processing the
3427: * replacement text of the entity
3428: * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
3429: * appending #x20 to the normalized value, except that only a single
3430: * #x20 is appended for a "#xD#xA" sequence that is part of an external
3431: * parsed entity or the literal entity value of an internal parsed entity
3432: * - other characters are processed by appending them to the normalized value
1.130 daniel 3433: * If the declared value is not CDATA, then the XML processor must further
3434: * process the normalized attribute value by discarding any leading and
3435: * trailing space (#x20) characters, and by replacing sequences of space
3436: * (#x20) characters by a single space (#x20) character.
3437: * All attributes for which no declaration has been read should be treated
3438: * by a non-validating parser as if declared CDATA.
1.129 daniel 3439: *
3440: * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
1.29 daniel 3441: */
3442:
1.123 daniel 3443: xmlChar *
1.55 daniel 3444: xmlParseAttValue(xmlParserCtxtPtr ctxt) {
1.129 daniel 3445: xmlChar limit = 0;
3446: xmlChar *buffer = NULL;
3447: int buffer_size = 0;
3448: xmlChar *out = NULL;
3449:
3450: xmlChar *current = NULL;
3451: xmlEntityPtr ent;
3452: xmlChar cur;
3453:
1.29 daniel 3454:
1.91 daniel 3455: SHRINK;
1.151 daniel 3456: if (NXT(0) == '"') {
1.96 daniel 3457: ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.129 daniel 3458: limit = '"';
1.40 daniel 3459: NEXT;
1.151 daniel 3460: } else if (NXT(0) == '\'') {
1.129 daniel 3461: limit = '\'';
1.96 daniel 3462: ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.40 daniel 3463: NEXT;
1.29 daniel 3464: } else {
1.123 daniel 3465: ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
1.55 daniel 3466: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3467: ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
1.59 daniel 3468: ctxt->wellFormed = 0;
1.129 daniel 3469: return(NULL);
1.29 daniel 3470: }
3471:
1.129 daniel 3472: /*
3473: * allocate a translation buffer.
3474: */
1.140 daniel 3475: buffer_size = XML_PARSER_BUFFER_SIZE;
1.129 daniel 3476: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
3477: if (buffer == NULL) {
3478: perror("xmlParseAttValue: malloc failed");
3479: return(NULL);
3480: }
3481: out = buffer;
3482:
3483: /*
3484: * Ok loop until we reach one of the ending char or a size limit.
3485: */
3486: cur = CUR;
1.156 daniel 3487: while (((NXT(0) != limit) && (cur != '<')) || (ctxt->token != 0)) {
1.129 daniel 3488: if (cur == 0) break;
3489: if ((cur == '&') && (NXT(1) == '#')) {
3490: int val = xmlParseCharRef(ctxt);
3491: *out++ = val;
3492: } else if (cur == '&') {
3493: ent = xmlParseEntityRef(ctxt);
3494: if ((ent != NULL) &&
3495: (ctxt->replaceEntities != 0)) {
3496: current = ent->content;
3497: while (*current != 0) {
3498: *out++ = *current++;
3499: if (out - buffer > buffer_size - 10) {
3500: int index = out - buffer;
3501:
3502: growBuffer(buffer);
3503: out = &buffer[index];
3504: }
3505: }
3506: } else if (ent != NULL) {
3507: int i = xmlStrlen(ent->name);
3508: const xmlChar *cur = ent->name;
3509:
3510: *out++ = '&';
3511: if (out - buffer > buffer_size - i - 10) {
3512: int index = out - buffer;
3513:
3514: growBuffer(buffer);
3515: out = &buffer[index];
3516: }
3517: for (;i > 0;i--)
3518: *out++ = *cur++;
3519: *out++ = ';';
3520: }
3521: } else {
1.156 daniel 3522: /* invalid for UTF-8 , use COPY(out); !!! */
1.129 daniel 3523: if ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9)) {
1.130 daniel 3524: *out++ = 0x20;
3525: if (out - buffer > buffer_size - 10) {
3526: int index = out - buffer;
3527:
3528: growBuffer(buffer);
3529: out = &buffer[index];
1.129 daniel 3530: }
3531: } else {
3532: *out++ = cur;
3533: if (out - buffer > buffer_size - 10) {
3534: int index = out - buffer;
3535:
3536: growBuffer(buffer);
3537: out = &buffer[index];
3538: }
3539: }
3540: NEXT;
3541: }
3542: cur = CUR;
3543: }
3544: *out++ = 0;
1.152 daniel 3545: if (RAW == '<') {
1.129 daniel 3546: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3547: ctxt->sax->error(ctxt->userData,
3548: "Unescaped '<' not allowed in attributes values\n");
3549: ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
3550: ctxt->wellFormed = 0;
1.152 daniel 3551: } else if (RAW != limit) {
1.129 daniel 3552: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3553: ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
3554: ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
3555: ctxt->wellFormed = 0;
3556: } else
3557: NEXT;
3558: return(buffer);
1.29 daniel 3559: }
3560:
1.50 daniel 3561: /**
3562: * xmlParseSystemLiteral:
3563: * @ctxt: an XML parser context
3564: *
3565: * parse an XML Literal
1.21 daniel 3566: *
1.22 daniel 3567: * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
1.68 daniel 3568: *
3569: * Returns the SystemLiteral parsed or NULL
1.21 daniel 3570: */
3571:
1.123 daniel 3572: xmlChar *
1.55 daniel 3573: xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
1.135 daniel 3574: xmlChar *buf = NULL;
3575: int len = 0;
1.140 daniel 3576: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 3577: int cur, l;
1.135 daniel 3578: xmlChar stop;
1.168 daniel 3579: int state = ctxt->instate;
1.21 daniel 3580:
1.91 daniel 3581: SHRINK;
1.152 daniel 3582: if (RAW == '"') {
1.40 daniel 3583: NEXT;
1.135 daniel 3584: stop = '"';
1.152 daniel 3585: } else if (RAW == '\'') {
1.40 daniel 3586: NEXT;
1.135 daniel 3587: stop = '\'';
1.21 daniel 3588: } else {
1.55 daniel 3589: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3590: ctxt->sax->error(ctxt->userData,
3591: "SystemLiteral \" or ' expected\n");
1.123 daniel 3592: ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59 daniel 3593: ctxt->wellFormed = 0;
1.135 daniel 3594: return(NULL);
1.21 daniel 3595: }
3596:
1.135 daniel 3597: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
3598: if (buf == NULL) {
3599: fprintf(stderr, "malloc of %d byte failed\n", size);
3600: return(NULL);
3601: }
1.168 daniel 3602: ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
1.152 daniel 3603: cur = CUR_CHAR(l);
1.135 daniel 3604: while ((IS_CHAR(cur)) && (cur != stop)) {
1.152 daniel 3605: if (len + 5 >= size) {
1.135 daniel 3606: size *= 2;
3607: buf = xmlRealloc(buf, size * sizeof(xmlChar));
3608: if (buf == NULL) {
3609: fprintf(stderr, "realloc of %d byte failed\n", size);
1.168 daniel 3610: ctxt->instate = state;
1.135 daniel 3611: return(NULL);
3612: }
3613: }
1.152 daniel 3614: COPY_BUF(l,buf,len,cur);
3615: NEXTL(l);
3616: cur = CUR_CHAR(l);
1.135 daniel 3617: if (cur == 0) {
3618: GROW;
3619: SHRINK;
1.152 daniel 3620: cur = CUR_CHAR(l);
1.135 daniel 3621: }
3622: }
3623: buf[len] = 0;
1.168 daniel 3624: ctxt->instate = state;
1.135 daniel 3625: if (!IS_CHAR(cur)) {
3626: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3627: ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
3628: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
3629: ctxt->wellFormed = 0;
3630: } else {
3631: NEXT;
3632: }
3633: return(buf);
1.21 daniel 3634: }
3635:
1.50 daniel 3636: /**
3637: * xmlParsePubidLiteral:
3638: * @ctxt: an XML parser context
1.21 daniel 3639: *
1.50 daniel 3640: * parse an XML public literal
1.68 daniel 3641: *
3642: * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
3643: *
3644: * Returns the PubidLiteral parsed or NULL.
1.21 daniel 3645: */
3646:
1.123 daniel 3647: xmlChar *
1.55 daniel 3648: xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
1.135 daniel 3649: xmlChar *buf = NULL;
3650: int len = 0;
1.140 daniel 3651: int size = XML_PARSER_BUFFER_SIZE;
1.135 daniel 3652: xmlChar cur;
3653: xmlChar stop;
1.125 daniel 3654:
1.91 daniel 3655: SHRINK;
1.152 daniel 3656: if (RAW == '"') {
1.40 daniel 3657: NEXT;
1.135 daniel 3658: stop = '"';
1.152 daniel 3659: } else if (RAW == '\'') {
1.40 daniel 3660: NEXT;
1.135 daniel 3661: stop = '\'';
1.21 daniel 3662: } else {
1.55 daniel 3663: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3664: ctxt->sax->error(ctxt->userData,
3665: "SystemLiteral \" or ' expected\n");
1.123 daniel 3666: ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59 daniel 3667: ctxt->wellFormed = 0;
1.135 daniel 3668: return(NULL);
3669: }
3670: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
3671: if (buf == NULL) {
3672: fprintf(stderr, "malloc of %d byte failed\n", size);
3673: return(NULL);
3674: }
3675: cur = CUR;
3676: while ((IS_PUBIDCHAR(cur)) && (cur != stop)) {
3677: if (len + 1 >= size) {
3678: size *= 2;
3679: buf = xmlRealloc(buf, size * sizeof(xmlChar));
3680: if (buf == NULL) {
3681: fprintf(stderr, "realloc of %d byte failed\n", size);
3682: return(NULL);
3683: }
3684: }
3685: buf[len++] = cur;
3686: NEXT;
3687: cur = CUR;
3688: if (cur == 0) {
3689: GROW;
3690: SHRINK;
3691: cur = CUR;
3692: }
3693: }
3694: buf[len] = 0;
3695: if (cur != stop) {
3696: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3697: ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
3698: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
3699: ctxt->wellFormed = 0;
3700: } else {
3701: NEXT;
1.21 daniel 3702: }
1.135 daniel 3703: return(buf);
1.21 daniel 3704: }
3705:
1.50 daniel 3706: /**
3707: * xmlParseCharData:
3708: * @ctxt: an XML parser context
3709: * @cdata: int indicating whether we are within a CDATA section
3710: *
3711: * parse a CharData section.
3712: * if we are within a CDATA section ']]>' marks an end of section.
1.27 daniel 3713: *
1.151 daniel 3714: * The right angle bracket (>) may be represented using the string ">",
3715: * and must, for compatibility, be escaped using ">" or a character
3716: * reference when it appears in the string "]]>" in content, when that
3717: * string is not marking the end of a CDATA section.
3718: *
1.27 daniel 3719: * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
3720: */
3721:
1.55 daniel 3722: void
3723: xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
1.152 daniel 3724: xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
1.91 daniel 3725: int nbchar = 0;
1.152 daniel 3726: int cur, l;
1.27 daniel 3727:
1.91 daniel 3728: SHRINK;
1.152 daniel 3729: cur = CUR_CHAR(l);
1.160 daniel 3730: while ((IS_CHAR(cur)) && ((cur != '<') || (ctxt->token == '<')) &&
1.153 daniel 3731: ((cur != '&') || (ctxt->token == '&'))) {
1.97 daniel 3732: if ((cur == ']') && (NXT(1) == ']') &&
1.59 daniel 3733: (NXT(2) == '>')) {
3734: if (cdata) break;
3735: else {
3736: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.151 daniel 3737: ctxt->sax->error(ctxt->userData,
1.59 daniel 3738: "Sequence ']]>' not allowed in content\n");
1.123 daniel 3739: ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
1.151 daniel 3740: /* Should this be relaxed ??? I see a "must here */
3741: ctxt->wellFormed = 0;
1.59 daniel 3742: }
3743: }
1.152 daniel 3744: COPY_BUF(l,buf,nbchar,cur);
3745: if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
1.91 daniel 3746: /*
3747: * Ok the segment is to be consumed as chars.
3748: */
3749: if (ctxt->sax != NULL) {
3750: if (areBlanks(ctxt, buf, nbchar)) {
3751: if (ctxt->sax->ignorableWhitespace != NULL)
3752: ctxt->sax->ignorableWhitespace(ctxt->userData,
3753: buf, nbchar);
3754: } else {
3755: if (ctxt->sax->characters != NULL)
3756: ctxt->sax->characters(ctxt->userData, buf, nbchar);
3757: }
3758: }
3759: nbchar = 0;
3760: }
1.152 daniel 3761: NEXTL(l);
3762: cur = CUR_CHAR(l);
1.27 daniel 3763: }
1.91 daniel 3764: if (nbchar != 0) {
3765: /*
3766: * Ok the segment is to be consumed as chars.
3767: */
3768: if (ctxt->sax != NULL) {
3769: if (areBlanks(ctxt, buf, nbchar)) {
3770: if (ctxt->sax->ignorableWhitespace != NULL)
3771: ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
3772: } else {
3773: if (ctxt->sax->characters != NULL)
3774: ctxt->sax->characters(ctxt->userData, buf, nbchar);
3775: }
3776: }
1.45 daniel 3777: }
1.27 daniel 3778: }
3779:
1.50 daniel 3780: /**
3781: * xmlParseExternalID:
3782: * @ctxt: an XML parser context
1.123 daniel 3783: * @publicID: a xmlChar** receiving PubidLiteral
1.67 daniel 3784: * @strict: indicate whether we should restrict parsing to only
3785: * production [75], see NOTE below
1.50 daniel 3786: *
1.67 daniel 3787: * Parse an External ID or a Public ID
3788: *
3789: * NOTE: Productions [75] and [83] interract badly since [75] can generate
3790: * 'PUBLIC' S PubidLiteral S SystemLiteral
1.22 daniel 3791: *
3792: * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
3793: * | 'PUBLIC' S PubidLiteral S SystemLiteral
1.67 daniel 3794: *
3795: * [83] PublicID ::= 'PUBLIC' S PubidLiteral
3796: *
1.68 daniel 3797: * Returns the function returns SystemLiteral and in the second
1.67 daniel 3798: * case publicID receives PubidLiteral, is strict is off
3799: * it is possible to return NULL and have publicID set.
1.22 daniel 3800: */
3801:
1.123 daniel 3802: xmlChar *
3803: xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
3804: xmlChar *URI = NULL;
1.22 daniel 3805:
1.91 daniel 3806: SHRINK;
1.152 daniel 3807: if ((RAW == 'S') && (NXT(1) == 'Y') &&
1.40 daniel 3808: (NXT(2) == 'S') && (NXT(3) == 'T') &&
3809: (NXT(4) == 'E') && (NXT(5) == 'M')) {
3810: SKIP(6);
1.59 daniel 3811: if (!IS_BLANK(CUR)) {
3812: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3813: ctxt->sax->error(ctxt->userData,
1.59 daniel 3814: "Space required after 'SYSTEM'\n");
1.123 daniel 3815: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3816: ctxt->wellFormed = 0;
3817: }
1.42 daniel 3818: SKIP_BLANKS;
1.39 daniel 3819: URI = xmlParseSystemLiteral(ctxt);
1.59 daniel 3820: if (URI == NULL) {
1.55 daniel 3821: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3822: ctxt->sax->error(ctxt->userData,
1.39 daniel 3823: "xmlParseExternalID: SYSTEM, no URI\n");
1.123 daniel 3824: ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59 daniel 3825: ctxt->wellFormed = 0;
3826: }
1.152 daniel 3827: } else if ((RAW == 'P') && (NXT(1) == 'U') &&
1.40 daniel 3828: (NXT(2) == 'B') && (NXT(3) == 'L') &&
3829: (NXT(4) == 'I') && (NXT(5) == 'C')) {
3830: SKIP(6);
1.59 daniel 3831: if (!IS_BLANK(CUR)) {
3832: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3833: ctxt->sax->error(ctxt->userData,
1.59 daniel 3834: "Space required after 'PUBLIC'\n");
1.123 daniel 3835: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3836: ctxt->wellFormed = 0;
3837: }
1.42 daniel 3838: SKIP_BLANKS;
1.39 daniel 3839: *publicID = xmlParsePubidLiteral(ctxt);
1.59 daniel 3840: if (*publicID == NULL) {
1.55 daniel 3841: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3842: ctxt->sax->error(ctxt->userData,
1.39 daniel 3843: "xmlParseExternalID: PUBLIC, no Public Identifier\n");
1.123 daniel 3844: ctxt->errNo = XML_ERR_PUBID_REQUIRED;
1.59 daniel 3845: ctxt->wellFormed = 0;
3846: }
1.67 daniel 3847: if (strict) {
3848: /*
3849: * We don't handle [83] so "S SystemLiteral" is required.
3850: */
3851: if (!IS_BLANK(CUR)) {
3852: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3853: ctxt->sax->error(ctxt->userData,
1.67 daniel 3854: "Space required after the Public Identifier\n");
1.123 daniel 3855: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67 daniel 3856: ctxt->wellFormed = 0;
3857: }
3858: } else {
3859: /*
3860: * We handle [83] so we return immediately, if
3861: * "S SystemLiteral" is not detected. From a purely parsing
3862: * point of view that's a nice mess.
3863: */
1.135 daniel 3864: const xmlChar *ptr;
3865: GROW;
3866:
3867: ptr = CUR_PTR;
1.67 daniel 3868: if (!IS_BLANK(*ptr)) return(NULL);
3869:
3870: while (IS_BLANK(*ptr)) ptr++;
3871: if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
1.59 daniel 3872: }
1.42 daniel 3873: SKIP_BLANKS;
1.39 daniel 3874: URI = xmlParseSystemLiteral(ctxt);
1.59 daniel 3875: if (URI == NULL) {
1.55 daniel 3876: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3877: ctxt->sax->error(ctxt->userData,
1.39 daniel 3878: "xmlParseExternalID: PUBLIC, no URI\n");
1.123 daniel 3879: ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59 daniel 3880: ctxt->wellFormed = 0;
3881: }
1.22 daniel 3882: }
1.39 daniel 3883: return(URI);
1.22 daniel 3884: }
3885:
1.50 daniel 3886: /**
3887: * xmlParseComment:
1.69 daniel 3888: * @ctxt: an XML parser context
1.50 daniel 3889: *
1.3 veillard 3890: * Skip an XML (SGML) comment <!-- .... -->
1.38 daniel 3891: * The spec says that "For compatibility, the string "--" (double-hyphen)
3892: * must not occur within comments. "
1.22 daniel 3893: *
3894: * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1.3 veillard 3895: */
1.72 daniel 3896: void
1.114 daniel 3897: xmlParseComment(xmlParserCtxtPtr ctxt) {
1.135 daniel 3898: xmlChar *buf = NULL;
3899: int len = 0;
1.140 daniel 3900: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 3901: int q, ql;
3902: int r, rl;
3903: int cur, l;
1.140 daniel 3904: xmlParserInputState state;
1.3 veillard 3905:
3906: /*
1.22 daniel 3907: * Check that there is a comment right here.
1.3 veillard 3908: */
1.152 daniel 3909: if ((RAW != '<') || (NXT(1) != '!') ||
1.72 daniel 3910: (NXT(2) != '-') || (NXT(3) != '-')) return;
1.3 veillard 3911:
1.140 daniel 3912: state = ctxt->instate;
1.97 daniel 3913: ctxt->instate = XML_PARSER_COMMENT;
1.91 daniel 3914: SHRINK;
1.40 daniel 3915: SKIP(4);
1.135 daniel 3916: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
3917: if (buf == NULL) {
3918: fprintf(stderr, "malloc of %d byte failed\n", size);
1.140 daniel 3919: ctxt->instate = state;
1.135 daniel 3920: return;
3921: }
1.152 daniel 3922: q = CUR_CHAR(ql);
3923: NEXTL(ql);
3924: r = CUR_CHAR(rl);
3925: NEXTL(rl);
3926: cur = CUR_CHAR(l);
1.135 daniel 3927: while (IS_CHAR(cur) &&
3928: ((cur != '>') ||
3929: (r != '-') || (q != '-'))) {
3930: if ((r == '-') && (q == '-')) {
1.55 daniel 3931: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3932: ctxt->sax->error(ctxt->userData,
1.38 daniel 3933: "Comment must not contain '--' (double-hyphen)`\n");
1.123 daniel 3934: ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
1.59 daniel 3935: ctxt->wellFormed = 0;
3936: }
1.152 daniel 3937: if (len + 5 >= size) {
1.135 daniel 3938: size *= 2;
3939: buf = xmlRealloc(buf, size * sizeof(xmlChar));
3940: if (buf == NULL) {
3941: fprintf(stderr, "realloc of %d byte failed\n", size);
1.140 daniel 3942: ctxt->instate = state;
1.135 daniel 3943: return;
3944: }
3945: }
1.152 daniel 3946: COPY_BUF(ql,buf,len,q);
1.135 daniel 3947: q = r;
1.152 daniel 3948: ql = rl;
1.135 daniel 3949: r = cur;
1.152 daniel 3950: rl = l;
3951: NEXTL(l);
3952: cur = CUR_CHAR(l);
1.135 daniel 3953: if (cur == 0) {
3954: SHRINK;
3955: GROW;
1.152 daniel 3956: cur = CUR_CHAR(l);
1.135 daniel 3957: }
1.3 veillard 3958: }
1.135 daniel 3959: buf[len] = 0;
3960: if (!IS_CHAR(cur)) {
1.55 daniel 3961: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3962: ctxt->sax->error(ctxt->userData,
1.135 daniel 3963: "Comment not terminated \n<!--%.50s\n", buf);
1.123 daniel 3964: ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
1.59 daniel 3965: ctxt->wellFormed = 0;
1.3 veillard 3966: } else {
1.40 daniel 3967: NEXT;
1.114 daniel 3968: if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
1.135 daniel 3969: ctxt->sax->comment(ctxt->userData, buf);
3970: xmlFree(buf);
1.3 veillard 3971: }
1.140 daniel 3972: ctxt->instate = state;
1.3 veillard 3973: }
3974:
1.50 daniel 3975: /**
3976: * xmlParsePITarget:
3977: * @ctxt: an XML parser context
3978: *
3979: * parse the name of a PI
1.22 daniel 3980: *
3981: * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
1.68 daniel 3982: *
3983: * Returns the PITarget name or NULL
1.22 daniel 3984: */
3985:
1.123 daniel 3986: xmlChar *
1.55 daniel 3987: xmlParsePITarget(xmlParserCtxtPtr ctxt) {
1.123 daniel 3988: xmlChar *name;
1.22 daniel 3989:
3990: name = xmlParseName(ctxt);
1.139 daniel 3991: if ((name != NULL) &&
1.22 daniel 3992: ((name[0] == 'x') || (name[0] == 'X')) &&
1.31 daniel 3993: ((name[1] == 'm') || (name[1] == 'M')) &&
3994: ((name[2] == 'l') || (name[2] == 'L'))) {
1.139 daniel 3995: int i;
1.151 daniel 3996: if ((name[0] = 'x') && (name[1] == 'm') &&
3997: (name[2] = 'l') && (name[3] == 0)) {
3998: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3999: ctxt->sax->error(ctxt->userData,
4000: "XML declaration allowed only at the start of the document\n");
4001: ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
4002: ctxt->wellFormed = 0;
4003: return(name);
4004: } else if (name[3] == 0) {
4005: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4006: ctxt->sax->error(ctxt->userData, "Invalid PI name\n");
4007: ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
4008: ctxt->wellFormed = 0;
4009: return(name);
4010: }
1.139 daniel 4011: for (i = 0;;i++) {
4012: if (xmlW3CPIs[i] == NULL) break;
4013: if (!xmlStrcmp(name, (const xmlChar *)xmlW3CPIs[i]))
4014: return(name);
4015: }
4016: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
4017: ctxt->sax->warning(ctxt->userData,
1.122 daniel 4018: "xmlParsePItarget: invalid name prefix 'xml'\n");
1.123 daniel 4019: ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
1.122 daniel 4020: }
1.22 daniel 4021: }
4022: return(name);
4023: }
4024:
1.50 daniel 4025: /**
4026: * xmlParsePI:
4027: * @ctxt: an XML parser context
4028: *
4029: * parse an XML Processing Instruction.
1.22 daniel 4030: *
4031: * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1.68 daniel 4032: *
1.69 daniel 4033: * The processing is transfered to SAX once parsed.
1.3 veillard 4034: */
4035:
1.55 daniel 4036: void
4037: xmlParsePI(xmlParserCtxtPtr ctxt) {
1.135 daniel 4038: xmlChar *buf = NULL;
4039: int len = 0;
1.140 daniel 4040: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 4041: int cur, l;
1.123 daniel 4042: xmlChar *target;
1.140 daniel 4043: xmlParserInputState state;
1.22 daniel 4044:
1.152 daniel 4045: if ((RAW == '<') && (NXT(1) == '?')) {
1.140 daniel 4046: state = ctxt->instate;
4047: ctxt->instate = XML_PARSER_PI;
1.3 veillard 4048: /*
4049: * this is a Processing Instruction.
4050: */
1.40 daniel 4051: SKIP(2);
1.91 daniel 4052: SHRINK;
1.3 veillard 4053:
4054: /*
1.22 daniel 4055: * Parse the target name and check for special support like
4056: * namespace.
1.3 veillard 4057: */
1.22 daniel 4058: target = xmlParsePITarget(ctxt);
4059: if (target != NULL) {
1.156 daniel 4060: if ((RAW == '?') && (NXT(1) == '>')) {
4061: SKIP(2);
4062:
4063: /*
4064: * SAX: PI detected.
4065: */
4066: if ((ctxt->sax) &&
4067: (ctxt->sax->processingInstruction != NULL))
4068: ctxt->sax->processingInstruction(ctxt->userData,
4069: target, NULL);
4070: ctxt->instate = state;
1.170 ! daniel 4071: xmlFree(target);
1.156 daniel 4072: return;
4073: }
1.135 daniel 4074: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
4075: if (buf == NULL) {
4076: fprintf(stderr, "malloc of %d byte failed\n", size);
1.140 daniel 4077: ctxt->instate = state;
1.135 daniel 4078: return;
4079: }
4080: cur = CUR;
4081: if (!IS_BLANK(cur)) {
1.114 daniel 4082: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4083: ctxt->sax->error(ctxt->userData,
4084: "xmlParsePI: PI %s space expected\n", target);
1.123 daniel 4085: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.114 daniel 4086: ctxt->wellFormed = 0;
4087: }
4088: SKIP_BLANKS;
1.152 daniel 4089: cur = CUR_CHAR(l);
1.135 daniel 4090: while (IS_CHAR(cur) &&
4091: ((cur != '?') || (NXT(1) != '>'))) {
1.152 daniel 4092: if (len + 5 >= size) {
1.135 daniel 4093: size *= 2;
4094: buf = xmlRealloc(buf, size * sizeof(xmlChar));
4095: if (buf == NULL) {
4096: fprintf(stderr, "realloc of %d byte failed\n", size);
1.140 daniel 4097: ctxt->instate = state;
1.135 daniel 4098: return;
4099: }
4100: }
1.152 daniel 4101: COPY_BUF(l,buf,len,cur);
4102: NEXTL(l);
4103: cur = CUR_CHAR(l);
1.135 daniel 4104: if (cur == 0) {
4105: SHRINK;
4106: GROW;
1.152 daniel 4107: cur = CUR_CHAR(l);
1.135 daniel 4108: }
4109: }
4110: buf[len] = 0;
1.152 daniel 4111: if (cur != '?') {
1.72 daniel 4112: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4113: ctxt->sax->error(ctxt->userData,
1.72 daniel 4114: "xmlParsePI: PI %s never end ...\n", target);
1.123 daniel 4115: ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
1.72 daniel 4116: ctxt->wellFormed = 0;
1.22 daniel 4117: } else {
1.72 daniel 4118: SKIP(2);
1.44 daniel 4119:
1.72 daniel 4120: /*
4121: * SAX: PI detected.
4122: */
4123: if ((ctxt->sax) &&
4124: (ctxt->sax->processingInstruction != NULL))
1.99 daniel 4125: ctxt->sax->processingInstruction(ctxt->userData,
1.135 daniel 4126: target, buf);
1.22 daniel 4127: }
1.135 daniel 4128: xmlFree(buf);
1.119 daniel 4129: xmlFree(target);
1.3 veillard 4130: } else {
1.55 daniel 4131: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.99 daniel 4132: ctxt->sax->error(ctxt->userData,
4133: "xmlParsePI : no target name\n");
1.123 daniel 4134: ctxt->errNo = XML_ERR_PI_NOT_STARTED;
1.59 daniel 4135: ctxt->wellFormed = 0;
1.22 daniel 4136: }
1.140 daniel 4137: ctxt->instate = state;
1.22 daniel 4138: }
4139: }
4140:
1.50 daniel 4141: /**
4142: * xmlParseNotationDecl:
4143: * @ctxt: an XML parser context
4144: *
4145: * parse a notation declaration
1.22 daniel 4146: *
4147: * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
4148: *
4149: * Hence there is actually 3 choices:
4150: * 'PUBLIC' S PubidLiteral
4151: * 'PUBLIC' S PubidLiteral S SystemLiteral
4152: * and 'SYSTEM' S SystemLiteral
1.50 daniel 4153: *
1.67 daniel 4154: * See the NOTE on xmlParseExternalID().
1.22 daniel 4155: */
4156:
1.55 daniel 4157: void
4158: xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4159: xmlChar *name;
4160: xmlChar *Pubid;
4161: xmlChar *Systemid;
1.22 daniel 4162:
1.152 daniel 4163: if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 4164: (NXT(2) == 'N') && (NXT(3) == 'O') &&
4165: (NXT(4) == 'T') && (NXT(5) == 'A') &&
4166: (NXT(6) == 'T') && (NXT(7) == 'I') &&
1.67 daniel 4167: (NXT(8) == 'O') && (NXT(9) == 'N')) {
1.91 daniel 4168: SHRINK;
1.40 daniel 4169: SKIP(10);
1.67 daniel 4170: if (!IS_BLANK(CUR)) {
4171: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4172: ctxt->sax->error(ctxt->userData,
4173: "Space required after '<!NOTATION'\n");
1.123 daniel 4174: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67 daniel 4175: ctxt->wellFormed = 0;
4176: return;
4177: }
4178: SKIP_BLANKS;
1.22 daniel 4179:
4180: name = xmlParseName(ctxt);
4181: if (name == NULL) {
1.55 daniel 4182: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4183: ctxt->sax->error(ctxt->userData,
4184: "NOTATION: Name expected here\n");
1.123 daniel 4185: ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.67 daniel 4186: ctxt->wellFormed = 0;
4187: return;
4188: }
4189: if (!IS_BLANK(CUR)) {
4190: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4191: ctxt->sax->error(ctxt->userData,
1.67 daniel 4192: "Space required after the NOTATION name'\n");
1.123 daniel 4193: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4194: ctxt->wellFormed = 0;
1.22 daniel 4195: return;
4196: }
1.42 daniel 4197: SKIP_BLANKS;
1.67 daniel 4198:
1.22 daniel 4199: /*
1.67 daniel 4200: * Parse the IDs.
1.22 daniel 4201: */
1.160 daniel 4202: Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
1.67 daniel 4203: SKIP_BLANKS;
4204:
1.152 daniel 4205: if (RAW == '>') {
1.40 daniel 4206: NEXT;
1.72 daniel 4207: if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
1.74 daniel 4208: ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
1.67 daniel 4209: } else {
4210: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4211: ctxt->sax->error(ctxt->userData,
1.67 daniel 4212: "'>' required to close NOTATION declaration\n");
1.123 daniel 4213: ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.67 daniel 4214: ctxt->wellFormed = 0;
4215: }
1.119 daniel 4216: xmlFree(name);
4217: if (Systemid != NULL) xmlFree(Systemid);
4218: if (Pubid != NULL) xmlFree(Pubid);
1.22 daniel 4219: }
4220: }
4221:
1.50 daniel 4222: /**
4223: * xmlParseEntityDecl:
4224: * @ctxt: an XML parser context
4225: *
4226: * parse <!ENTITY declarations
1.22 daniel 4227: *
4228: * [70] EntityDecl ::= GEDecl | PEDecl
4229: *
4230: * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
4231: *
4232: * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
4233: *
4234: * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
4235: *
4236: * [74] PEDef ::= EntityValue | ExternalID
1.24 daniel 4237: *
4238: * [76] NDataDecl ::= S 'NDATA' S Name
1.99 daniel 4239: *
4240: * [ VC: Notation Declared ]
1.116 daniel 4241: * The Name must match the declared name of a notation.
1.22 daniel 4242: */
4243:
1.55 daniel 4244: void
4245: xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4246: xmlChar *name = NULL;
4247: xmlChar *value = NULL;
4248: xmlChar *URI = NULL, *literal = NULL;
4249: xmlChar *ndata = NULL;
1.39 daniel 4250: int isParameter = 0;
1.123 daniel 4251: xmlChar *orig = NULL;
1.22 daniel 4252:
1.94 daniel 4253: GROW;
1.152 daniel 4254: if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 4255: (NXT(2) == 'E') && (NXT(3) == 'N') &&
4256: (NXT(4) == 'T') && (NXT(5) == 'I') &&
1.59 daniel 4257: (NXT(6) == 'T') && (NXT(7) == 'Y')) {
1.96 daniel 4258: ctxt->instate = XML_PARSER_ENTITY_DECL;
1.91 daniel 4259: SHRINK;
1.40 daniel 4260: SKIP(8);
1.59 daniel 4261: if (!IS_BLANK(CUR)) {
4262: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4263: ctxt->sax->error(ctxt->userData,
4264: "Space required after '<!ENTITY'\n");
1.123 daniel 4265: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4266: ctxt->wellFormed = 0;
4267: }
4268: SKIP_BLANKS;
1.40 daniel 4269:
1.152 daniel 4270: if (RAW == '%') {
1.40 daniel 4271: NEXT;
1.59 daniel 4272: if (!IS_BLANK(CUR)) {
4273: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4274: ctxt->sax->error(ctxt->userData,
4275: "Space required after '%'\n");
1.123 daniel 4276: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4277: ctxt->wellFormed = 0;
4278: }
1.42 daniel 4279: SKIP_BLANKS;
1.39 daniel 4280: isParameter = 1;
1.22 daniel 4281: }
4282:
4283: name = xmlParseName(ctxt);
1.24 daniel 4284: if (name == NULL) {
1.55 daniel 4285: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4286: ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
1.123 daniel 4287: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4288: ctxt->wellFormed = 0;
1.24 daniel 4289: return;
4290: }
1.59 daniel 4291: if (!IS_BLANK(CUR)) {
4292: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4293: ctxt->sax->error(ctxt->userData,
1.59 daniel 4294: "Space required after the entity name\n");
1.123 daniel 4295: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4296: ctxt->wellFormed = 0;
4297: }
1.42 daniel 4298: SKIP_BLANKS;
1.24 daniel 4299:
1.22 daniel 4300: /*
1.68 daniel 4301: * handle the various case of definitions...
1.22 daniel 4302: */
1.39 daniel 4303: if (isParameter) {
1.152 daniel 4304: if ((RAW == '"') || (RAW == '\''))
1.78 daniel 4305: value = xmlParseEntityValue(ctxt, &orig);
1.39 daniel 4306: if (value) {
1.72 daniel 4307: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 4308: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 4309: XML_INTERNAL_PARAMETER_ENTITY,
4310: NULL, NULL, value);
4311: }
1.24 daniel 4312: else {
1.67 daniel 4313: URI = xmlParseExternalID(ctxt, &literal, 1);
1.169 daniel 4314: if ((URI == NULL) && (literal == NULL)) {
4315: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4316: ctxt->sax->error(ctxt->userData,
4317: "Entity value required\n");
4318: ctxt->errNo = XML_ERR_VALUE_REQUIRED;
4319: ctxt->wellFormed = 0;
4320: }
1.39 daniel 4321: if (URI) {
1.72 daniel 4322: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 4323: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 4324: XML_EXTERNAL_PARAMETER_ENTITY,
4325: literal, URI, NULL);
4326: }
1.24 daniel 4327: }
4328: } else {
1.152 daniel 4329: if ((RAW == '"') || (RAW == '\'')) {
1.78 daniel 4330: value = xmlParseEntityValue(ctxt, &orig);
1.72 daniel 4331: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 4332: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 4333: XML_INTERNAL_GENERAL_ENTITY,
4334: NULL, NULL, value);
4335: } else {
1.67 daniel 4336: URI = xmlParseExternalID(ctxt, &literal, 1);
1.169 daniel 4337: if ((URI == NULL) && (literal == NULL)) {
4338: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4339: ctxt->sax->error(ctxt->userData,
4340: "Entity value required\n");
4341: ctxt->errNo = XML_ERR_VALUE_REQUIRED;
4342: ctxt->wellFormed = 0;
4343: }
1.152 daniel 4344: if ((RAW != '>') && (!IS_BLANK(CUR))) {
1.59 daniel 4345: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4346: ctxt->sax->error(ctxt->userData,
1.59 daniel 4347: "Space required before 'NDATA'\n");
1.123 daniel 4348: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4349: ctxt->wellFormed = 0;
4350: }
1.42 daniel 4351: SKIP_BLANKS;
1.152 daniel 4352: if ((RAW == 'N') && (NXT(1) == 'D') &&
1.40 daniel 4353: (NXT(2) == 'A') && (NXT(3) == 'T') &&
4354: (NXT(4) == 'A')) {
4355: SKIP(5);
1.59 daniel 4356: if (!IS_BLANK(CUR)) {
4357: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4358: ctxt->sax->error(ctxt->userData,
1.59 daniel 4359: "Space required after 'NDATA'\n");
1.123 daniel 4360: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4361: ctxt->wellFormed = 0;
4362: }
1.42 daniel 4363: SKIP_BLANKS;
1.24 daniel 4364: ndata = xmlParseName(ctxt);
1.116 daniel 4365: if ((ctxt->sax != NULL) &&
4366: (ctxt->sax->unparsedEntityDecl != NULL))
4367: ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
1.39 daniel 4368: literal, URI, ndata);
4369: } else {
1.72 daniel 4370: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 4371: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 4372: XML_EXTERNAL_GENERAL_PARSED_ENTITY,
4373: literal, URI, NULL);
1.24 daniel 4374: }
4375: }
4376: }
1.42 daniel 4377: SKIP_BLANKS;
1.152 daniel 4378: if (RAW != '>') {
1.55 daniel 4379: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4380: ctxt->sax->error(ctxt->userData,
1.31 daniel 4381: "xmlParseEntityDecl: entity %s not terminated\n", name);
1.123 daniel 4382: ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.59 daniel 4383: ctxt->wellFormed = 0;
1.24 daniel 4384: } else
1.40 daniel 4385: NEXT;
1.78 daniel 4386: if (orig != NULL) {
4387: /*
1.98 daniel 4388: * Ugly mechanism to save the raw entity value.
1.78 daniel 4389: */
4390: xmlEntityPtr cur = NULL;
4391:
1.98 daniel 4392: if (isParameter) {
4393: if ((ctxt->sax != NULL) &&
4394: (ctxt->sax->getParameterEntity != NULL))
1.120 daniel 4395: cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.98 daniel 4396: } else {
4397: if ((ctxt->sax != NULL) &&
4398: (ctxt->sax->getEntity != NULL))
1.120 daniel 4399: cur = ctxt->sax->getEntity(ctxt->userData, name);
1.98 daniel 4400: }
4401: if (cur != NULL) {
4402: if (cur->orig != NULL)
1.119 daniel 4403: xmlFree(orig);
1.98 daniel 4404: else
4405: cur->orig = orig;
4406: } else
1.119 daniel 4407: xmlFree(orig);
1.78 daniel 4408: }
1.119 daniel 4409: if (name != NULL) xmlFree(name);
4410: if (value != NULL) xmlFree(value);
4411: if (URI != NULL) xmlFree(URI);
4412: if (literal != NULL) xmlFree(literal);
4413: if (ndata != NULL) xmlFree(ndata);
1.22 daniel 4414: }
4415: }
4416:
1.50 daniel 4417: /**
1.59 daniel 4418: * xmlParseDefaultDecl:
4419: * @ctxt: an XML parser context
4420: * @value: Receive a possible fixed default value for the attribute
4421: *
4422: * Parse an attribute default declaration
4423: *
4424: * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
4425: *
1.99 daniel 4426: * [ VC: Required Attribute ]
1.117 daniel 4427: * if the default declaration is the keyword #REQUIRED, then the
4428: * attribute must be specified for all elements of the type in the
4429: * attribute-list declaration.
1.99 daniel 4430: *
4431: * [ VC: Attribute Default Legal ]
1.102 daniel 4432: * The declared default value must meet the lexical constraints of
4433: * the declared attribute type c.f. xmlValidateAttributeDecl()
1.99 daniel 4434: *
4435: * [ VC: Fixed Attribute Default ]
1.117 daniel 4436: * if an attribute has a default value declared with the #FIXED
4437: * keyword, instances of that attribute must match the default value.
1.99 daniel 4438: *
4439: * [ WFC: No < in Attribute Values ]
4440: * handled in xmlParseAttValue()
4441: *
1.59 daniel 4442: * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
4443: * or XML_ATTRIBUTE_FIXED.
4444: */
4445:
4446: int
1.123 daniel 4447: xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
1.59 daniel 4448: int val;
1.123 daniel 4449: xmlChar *ret;
1.59 daniel 4450:
4451: *value = NULL;
1.152 daniel 4452: if ((RAW == '#') && (NXT(1) == 'R') &&
1.59 daniel 4453: (NXT(2) == 'E') && (NXT(3) == 'Q') &&
4454: (NXT(4) == 'U') && (NXT(5) == 'I') &&
4455: (NXT(6) == 'R') && (NXT(7) == 'E') &&
4456: (NXT(8) == 'D')) {
4457: SKIP(9);
4458: return(XML_ATTRIBUTE_REQUIRED);
4459: }
1.152 daniel 4460: if ((RAW == '#') && (NXT(1) == 'I') &&
1.59 daniel 4461: (NXT(2) == 'M') && (NXT(3) == 'P') &&
4462: (NXT(4) == 'L') && (NXT(5) == 'I') &&
4463: (NXT(6) == 'E') && (NXT(7) == 'D')) {
4464: SKIP(8);
4465: return(XML_ATTRIBUTE_IMPLIED);
4466: }
4467: val = XML_ATTRIBUTE_NONE;
1.152 daniel 4468: if ((RAW == '#') && (NXT(1) == 'F') &&
1.59 daniel 4469: (NXT(2) == 'I') && (NXT(3) == 'X') &&
4470: (NXT(4) == 'E') && (NXT(5) == 'D')) {
4471: SKIP(6);
4472: val = XML_ATTRIBUTE_FIXED;
4473: if (!IS_BLANK(CUR)) {
4474: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4475: ctxt->sax->error(ctxt->userData,
4476: "Space required after '#FIXED'\n");
1.123 daniel 4477: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4478: ctxt->wellFormed = 0;
4479: }
4480: SKIP_BLANKS;
4481: }
4482: ret = xmlParseAttValue(ctxt);
1.96 daniel 4483: ctxt->instate = XML_PARSER_DTD;
1.59 daniel 4484: if (ret == NULL) {
4485: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4486: ctxt->sax->error(ctxt->userData,
1.59 daniel 4487: "Attribute default value declaration error\n");
4488: ctxt->wellFormed = 0;
4489: } else
4490: *value = ret;
4491: return(val);
4492: }
4493:
4494: /**
1.66 daniel 4495: * xmlParseNotationType:
4496: * @ctxt: an XML parser context
4497: *
4498: * parse an Notation attribute type.
4499: *
1.99 daniel 4500: * Note: the leading 'NOTATION' S part has already being parsed...
4501: *
1.66 daniel 4502: * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
4503: *
1.99 daniel 4504: * [ VC: Notation Attributes ]
1.117 daniel 4505: * Values of this type must match one of the notation names included
1.99 daniel 4506: * in the declaration; all notation names in the declaration must be declared.
1.66 daniel 4507: *
4508: * Returns: the notation attribute tree built while parsing
4509: */
4510:
4511: xmlEnumerationPtr
4512: xmlParseNotationType(xmlParserCtxtPtr ctxt) {
1.123 daniel 4513: xmlChar *name;
1.66 daniel 4514: xmlEnumerationPtr ret = NULL, last = NULL, cur;
4515:
1.152 daniel 4516: if (RAW != '(') {
1.66 daniel 4517: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4518: ctxt->sax->error(ctxt->userData,
4519: "'(' required to start 'NOTATION'\n");
1.123 daniel 4520: ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.66 daniel 4521: ctxt->wellFormed = 0;
4522: return(NULL);
4523: }
1.91 daniel 4524: SHRINK;
1.66 daniel 4525: do {
4526: NEXT;
4527: SKIP_BLANKS;
4528: name = xmlParseName(ctxt);
4529: if (name == NULL) {
4530: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4531: ctxt->sax->error(ctxt->userData,
1.66 daniel 4532: "Name expected in NOTATION declaration\n");
1.123 daniel 4533: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.66 daniel 4534: ctxt->wellFormed = 0;
4535: return(ret);
4536: }
4537: cur = xmlCreateEnumeration(name);
1.119 daniel 4538: xmlFree(name);
1.66 daniel 4539: if (cur == NULL) return(ret);
4540: if (last == NULL) ret = last = cur;
4541: else {
4542: last->next = cur;
4543: last = cur;
4544: }
4545: SKIP_BLANKS;
1.152 daniel 4546: } while (RAW == '|');
4547: if (RAW != ')') {
1.66 daniel 4548: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4549: ctxt->sax->error(ctxt->userData,
1.66 daniel 4550: "')' required to finish NOTATION declaration\n");
1.123 daniel 4551: ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.66 daniel 4552: ctxt->wellFormed = 0;
1.170 ! daniel 4553: if ((last != NULL) && (last != ret))
! 4554: xmlFreeEnumeration(last);
1.66 daniel 4555: return(ret);
4556: }
4557: NEXT;
4558: return(ret);
4559: }
4560:
4561: /**
4562: * xmlParseEnumerationType:
4563: * @ctxt: an XML parser context
4564: *
4565: * parse an Enumeration attribute type.
4566: *
4567: * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
4568: *
1.99 daniel 4569: * [ VC: Enumeration ]
1.117 daniel 4570: * Values of this type must match one of the Nmtoken tokens in
1.99 daniel 4571: * the declaration
4572: *
1.66 daniel 4573: * Returns: the enumeration attribute tree built while parsing
4574: */
4575:
4576: xmlEnumerationPtr
4577: xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
1.123 daniel 4578: xmlChar *name;
1.66 daniel 4579: xmlEnumerationPtr ret = NULL, last = NULL, cur;
4580:
1.152 daniel 4581: if (RAW != '(') {
1.66 daniel 4582: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4583: ctxt->sax->error(ctxt->userData,
1.66 daniel 4584: "'(' required to start ATTLIST enumeration\n");
1.123 daniel 4585: ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
1.66 daniel 4586: ctxt->wellFormed = 0;
4587: return(NULL);
4588: }
1.91 daniel 4589: SHRINK;
1.66 daniel 4590: do {
4591: NEXT;
4592: SKIP_BLANKS;
4593: name = xmlParseNmtoken(ctxt);
4594: if (name == NULL) {
4595: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4596: ctxt->sax->error(ctxt->userData,
1.66 daniel 4597: "NmToken expected in ATTLIST enumeration\n");
1.123 daniel 4598: ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
1.66 daniel 4599: ctxt->wellFormed = 0;
4600: return(ret);
4601: }
4602: cur = xmlCreateEnumeration(name);
1.119 daniel 4603: xmlFree(name);
1.66 daniel 4604: if (cur == NULL) return(ret);
4605: if (last == NULL) ret = last = cur;
4606: else {
4607: last->next = cur;
4608: last = cur;
4609: }
4610: SKIP_BLANKS;
1.152 daniel 4611: } while (RAW == '|');
4612: if (RAW != ')') {
1.66 daniel 4613: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4614: ctxt->sax->error(ctxt->userData,
1.66 daniel 4615: "')' required to finish ATTLIST enumeration\n");
1.123 daniel 4616: ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
1.66 daniel 4617: ctxt->wellFormed = 0;
4618: return(ret);
4619: }
4620: NEXT;
4621: return(ret);
4622: }
4623:
4624: /**
1.50 daniel 4625: * xmlParseEnumeratedType:
4626: * @ctxt: an XML parser context
1.66 daniel 4627: * @tree: the enumeration tree built while parsing
1.50 daniel 4628: *
1.66 daniel 4629: * parse an Enumerated attribute type.
1.22 daniel 4630: *
4631: * [57] EnumeratedType ::= NotationType | Enumeration
4632: *
4633: * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
4634: *
1.50 daniel 4635: *
1.66 daniel 4636: * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
1.22 daniel 4637: */
4638:
1.66 daniel 4639: int
4640: xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
1.152 daniel 4641: if ((RAW == 'N') && (NXT(1) == 'O') &&
1.66 daniel 4642: (NXT(2) == 'T') && (NXT(3) == 'A') &&
4643: (NXT(4) == 'T') && (NXT(5) == 'I') &&
4644: (NXT(6) == 'O') && (NXT(7) == 'N')) {
4645: SKIP(8);
4646: if (!IS_BLANK(CUR)) {
4647: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4648: ctxt->sax->error(ctxt->userData,
4649: "Space required after 'NOTATION'\n");
1.123 daniel 4650: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.66 daniel 4651: ctxt->wellFormed = 0;
4652: return(0);
4653: }
4654: SKIP_BLANKS;
4655: *tree = xmlParseNotationType(ctxt);
4656: if (*tree == NULL) return(0);
4657: return(XML_ATTRIBUTE_NOTATION);
4658: }
4659: *tree = xmlParseEnumerationType(ctxt);
4660: if (*tree == NULL) return(0);
4661: return(XML_ATTRIBUTE_ENUMERATION);
1.22 daniel 4662: }
4663:
1.50 daniel 4664: /**
4665: * xmlParseAttributeType:
4666: * @ctxt: an XML parser context
1.66 daniel 4667: * @tree: the enumeration tree built while parsing
1.50 daniel 4668: *
1.59 daniel 4669: * parse the Attribute list def for an element
1.22 daniel 4670: *
4671: * [54] AttType ::= StringType | TokenizedType | EnumeratedType
4672: *
4673: * [55] StringType ::= 'CDATA'
4674: *
4675: * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
4676: * 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
1.50 daniel 4677: *
1.102 daniel 4678: * Validity constraints for attribute values syntax are checked in
4679: * xmlValidateAttributeValue()
4680: *
1.99 daniel 4681: * [ VC: ID ]
1.117 daniel 4682: * Values of type ID must match the Name production. A name must not
1.99 daniel 4683: * appear more than once in an XML document as a value of this type;
4684: * i.e., ID values must uniquely identify the elements which bear them.
4685: *
4686: * [ VC: One ID per Element Type ]
1.117 daniel 4687: * No element type may have more than one ID attribute specified.
1.99 daniel 4688: *
4689: * [ VC: ID Attribute Default ]
1.117 daniel 4690: * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
1.99 daniel 4691: *
4692: * [ VC: IDREF ]
1.102 daniel 4693: * Values of type IDREF must match the Name production, and values
1.140 daniel 4694: * of type IDREFS must match Names; each IDREF Name must match the value
1.117 daniel 4695: * of an ID attribute on some element in the XML document; i.e. IDREF
1.99 daniel 4696: * values must match the value of some ID attribute.
4697: *
4698: * [ VC: Entity Name ]
1.102 daniel 4699: * Values of type ENTITY must match the Name production, values
1.140 daniel 4700: * of type ENTITIES must match Names; each Entity Name must match the
1.117 daniel 4701: * name of an unparsed entity declared in the DTD.
1.99 daniel 4702: *
4703: * [ VC: Name Token ]
1.102 daniel 4704: * Values of type NMTOKEN must match the Nmtoken production; values
1.99 daniel 4705: * of type NMTOKENS must match Nmtokens.
4706: *
1.69 daniel 4707: * Returns the attribute type
1.22 daniel 4708: */
1.59 daniel 4709: int
1.66 daniel 4710: xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
1.91 daniel 4711: SHRINK;
1.152 daniel 4712: if ((RAW == 'C') && (NXT(1) == 'D') &&
1.40 daniel 4713: (NXT(2) == 'A') && (NXT(3) == 'T') &&
4714: (NXT(4) == 'A')) {
4715: SKIP(5);
1.66 daniel 4716: return(XML_ATTRIBUTE_CDATA);
1.152 daniel 4717: } else if ((RAW == 'I') && (NXT(1) == 'D') &&
1.40 daniel 4718: (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.97 daniel 4719: (NXT(4) == 'F') && (NXT(5) == 'S')) {
4720: SKIP(6);
4721: return(XML_ATTRIBUTE_IDREFS);
1.152 daniel 4722: } else if ((RAW == 'I') && (NXT(1) == 'D') &&
1.97 daniel 4723: (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.40 daniel 4724: (NXT(4) == 'F')) {
4725: SKIP(5);
1.59 daniel 4726: return(XML_ATTRIBUTE_IDREF);
1.152 daniel 4727: } else if ((RAW == 'I') && (NXT(1) == 'D')) {
1.66 daniel 4728: SKIP(2);
4729: return(XML_ATTRIBUTE_ID);
1.152 daniel 4730: } else if ((RAW == 'E') && (NXT(1) == 'N') &&
1.40 daniel 4731: (NXT(2) == 'T') && (NXT(3) == 'I') &&
4732: (NXT(4) == 'T') && (NXT(5) == 'Y')) {
4733: SKIP(6);
1.59 daniel 4734: return(XML_ATTRIBUTE_ENTITY);
1.152 daniel 4735: } else if ((RAW == 'E') && (NXT(1) == 'N') &&
1.40 daniel 4736: (NXT(2) == 'T') && (NXT(3) == 'I') &&
4737: (NXT(4) == 'T') && (NXT(5) == 'I') &&
4738: (NXT(6) == 'E') && (NXT(7) == 'S')) {
4739: SKIP(8);
1.59 daniel 4740: return(XML_ATTRIBUTE_ENTITIES);
1.152 daniel 4741: } else if ((RAW == 'N') && (NXT(1) == 'M') &&
1.40 daniel 4742: (NXT(2) == 'T') && (NXT(3) == 'O') &&
4743: (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.66 daniel 4744: (NXT(6) == 'N') && (NXT(7) == 'S')) {
4745: SKIP(8);
4746: return(XML_ATTRIBUTE_NMTOKENS);
1.152 daniel 4747: } else if ((RAW == 'N') && (NXT(1) == 'M') &&
1.66 daniel 4748: (NXT(2) == 'T') && (NXT(3) == 'O') &&
4749: (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.40 daniel 4750: (NXT(6) == 'N')) {
4751: SKIP(7);
1.59 daniel 4752: return(XML_ATTRIBUTE_NMTOKEN);
1.22 daniel 4753: }
1.66 daniel 4754: return(xmlParseEnumeratedType(ctxt, tree));
1.22 daniel 4755: }
4756:
1.50 daniel 4757: /**
4758: * xmlParseAttributeListDecl:
4759: * @ctxt: an XML parser context
4760: *
4761: * : parse the Attribute list def for an element
1.22 daniel 4762: *
4763: * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
4764: *
4765: * [53] AttDef ::= S Name S AttType S DefaultDecl
1.50 daniel 4766: *
1.22 daniel 4767: */
1.55 daniel 4768: void
4769: xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4770: xmlChar *elemName;
4771: xmlChar *attrName;
1.103 daniel 4772: xmlEnumerationPtr tree;
1.22 daniel 4773:
1.152 daniel 4774: if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 4775: (NXT(2) == 'A') && (NXT(3) == 'T') &&
4776: (NXT(4) == 'T') && (NXT(5) == 'L') &&
4777: (NXT(6) == 'I') && (NXT(7) == 'S') &&
1.59 daniel 4778: (NXT(8) == 'T')) {
1.40 daniel 4779: SKIP(9);
1.59 daniel 4780: if (!IS_BLANK(CUR)) {
4781: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4782: ctxt->sax->error(ctxt->userData,
4783: "Space required after '<!ATTLIST'\n");
1.123 daniel 4784: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4785: ctxt->wellFormed = 0;
4786: }
1.42 daniel 4787: SKIP_BLANKS;
1.59 daniel 4788: elemName = xmlParseName(ctxt);
4789: if (elemName == NULL) {
1.55 daniel 4790: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4791: ctxt->sax->error(ctxt->userData,
4792: "ATTLIST: no name for Element\n");
1.123 daniel 4793: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4794: ctxt->wellFormed = 0;
1.22 daniel 4795: return;
4796: }
1.42 daniel 4797: SKIP_BLANKS;
1.152 daniel 4798: while (RAW != '>') {
1.123 daniel 4799: const xmlChar *check = CUR_PTR;
1.59 daniel 4800: int type;
4801: int def;
1.123 daniel 4802: xmlChar *defaultValue = NULL;
1.59 daniel 4803:
1.103 daniel 4804: tree = NULL;
1.59 daniel 4805: attrName = xmlParseName(ctxt);
4806: if (attrName == NULL) {
4807: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4808: ctxt->sax->error(ctxt->userData,
4809: "ATTLIST: no name for Attribute\n");
1.123 daniel 4810: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4811: ctxt->wellFormed = 0;
4812: break;
4813: }
1.97 daniel 4814: GROW;
1.59 daniel 4815: if (!IS_BLANK(CUR)) {
4816: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4817: ctxt->sax->error(ctxt->userData,
1.59 daniel 4818: "Space required after the attribute name\n");
1.123 daniel 4819: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4820: ctxt->wellFormed = 0;
1.170 ! daniel 4821: if (attrName != NULL)
! 4822: xmlFree(attrName);
! 4823: if (defaultValue != NULL)
! 4824: xmlFree(defaultValue);
1.59 daniel 4825: break;
4826: }
4827: SKIP_BLANKS;
4828:
1.66 daniel 4829: type = xmlParseAttributeType(ctxt, &tree);
1.170 ! daniel 4830: if (type <= 0) {
! 4831: if (attrName != NULL)
! 4832: xmlFree(attrName);
! 4833: if (defaultValue != NULL)
! 4834: xmlFree(defaultValue);
! 4835: break;
! 4836: }
1.22 daniel 4837:
1.97 daniel 4838: GROW;
1.59 daniel 4839: if (!IS_BLANK(CUR)) {
4840: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4841: ctxt->sax->error(ctxt->userData,
1.59 daniel 4842: "Space required after the attribute type\n");
1.123 daniel 4843: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4844: ctxt->wellFormed = 0;
1.170 ! daniel 4845: if (attrName != NULL)
! 4846: xmlFree(attrName);
! 4847: if (defaultValue != NULL)
! 4848: xmlFree(defaultValue);
! 4849: if (tree != NULL)
! 4850: xmlFreeEnumeration(tree);
1.59 daniel 4851: break;
4852: }
1.42 daniel 4853: SKIP_BLANKS;
1.59 daniel 4854:
4855: def = xmlParseDefaultDecl(ctxt, &defaultValue);
1.170 ! daniel 4856: if (def <= 0) {
! 4857: if (attrName != NULL)
! 4858: xmlFree(attrName);
! 4859: if (defaultValue != NULL)
! 4860: xmlFree(defaultValue);
! 4861: if (tree != NULL)
! 4862: xmlFreeEnumeration(tree);
! 4863: break;
! 4864: }
1.59 daniel 4865:
1.97 daniel 4866: GROW;
1.152 daniel 4867: if (RAW != '>') {
1.59 daniel 4868: if (!IS_BLANK(CUR)) {
4869: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4870: ctxt->sax->error(ctxt->userData,
1.59 daniel 4871: "Space required after the attribute default value\n");
1.123 daniel 4872: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4873: ctxt->wellFormed = 0;
1.170 ! daniel 4874: if (attrName != NULL)
! 4875: xmlFree(attrName);
! 4876: if (defaultValue != NULL)
! 4877: xmlFree(defaultValue);
! 4878: if (tree != NULL)
! 4879: xmlFreeEnumeration(tree);
1.59 daniel 4880: break;
4881: }
4882: SKIP_BLANKS;
4883: }
1.40 daniel 4884: if (check == CUR_PTR) {
1.55 daniel 4885: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4886: ctxt->sax->error(ctxt->userData,
1.59 daniel 4887: "xmlParseAttributeListDecl: detected internal error\n");
1.123 daniel 4888: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.170 ! daniel 4889: if (attrName != NULL)
! 4890: xmlFree(attrName);
! 4891: if (defaultValue != NULL)
! 4892: xmlFree(defaultValue);
! 4893: if (tree != NULL)
! 4894: xmlFreeEnumeration(tree);
1.22 daniel 4895: break;
4896: }
1.72 daniel 4897: if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
1.74 daniel 4898: ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
1.66 daniel 4899: type, def, defaultValue, tree);
1.59 daniel 4900: if (attrName != NULL)
1.119 daniel 4901: xmlFree(attrName);
1.59 daniel 4902: if (defaultValue != NULL)
1.119 daniel 4903: xmlFree(defaultValue);
1.97 daniel 4904: GROW;
1.22 daniel 4905: }
1.152 daniel 4906: if (RAW == '>')
1.40 daniel 4907: NEXT;
1.22 daniel 4908:
1.119 daniel 4909: xmlFree(elemName);
1.22 daniel 4910: }
4911: }
4912:
1.50 daniel 4913: /**
1.61 daniel 4914: * xmlParseElementMixedContentDecl:
4915: * @ctxt: an XML parser context
4916: *
4917: * parse the declaration for a Mixed Element content
4918: * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
4919: *
4920: * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
4921: * '(' S? '#PCDATA' S? ')'
4922: *
1.99 daniel 4923: * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
4924: *
4925: * [ VC: No Duplicate Types ]
1.117 daniel 4926: * The same name must not appear more than once in a single
4927: * mixed-content declaration.
1.99 daniel 4928: *
1.61 daniel 4929: * returns: the list of the xmlElementContentPtr describing the element choices
4930: */
4931: xmlElementContentPtr
1.62 daniel 4932: xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
1.64 daniel 4933: xmlElementContentPtr ret = NULL, cur = NULL, n;
1.123 daniel 4934: xmlChar *elem = NULL;
1.61 daniel 4935:
1.97 daniel 4936: GROW;
1.152 daniel 4937: if ((RAW == '#') && (NXT(1) == 'P') &&
1.61 daniel 4938: (NXT(2) == 'C') && (NXT(3) == 'D') &&
4939: (NXT(4) == 'A') && (NXT(5) == 'T') &&
4940: (NXT(6) == 'A')) {
4941: SKIP(7);
4942: SKIP_BLANKS;
1.91 daniel 4943: SHRINK;
1.152 daniel 4944: if (RAW == ')') {
1.63 daniel 4945: NEXT;
4946: ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
1.152 daniel 4947: if (RAW == '*') {
1.136 daniel 4948: ret->ocur = XML_ELEMENT_CONTENT_MULT;
4949: NEXT;
4950: }
1.63 daniel 4951: return(ret);
4952: }
1.152 daniel 4953: if ((RAW == '(') || (RAW == '|')) {
1.61 daniel 4954: ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
4955: if (ret == NULL) return(NULL);
1.99 daniel 4956: }
1.152 daniel 4957: while (RAW == '|') {
1.64 daniel 4958: NEXT;
1.61 daniel 4959: if (elem == NULL) {
4960: ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
4961: if (ret == NULL) return(NULL);
4962: ret->c1 = cur;
1.64 daniel 4963: cur = ret;
1.61 daniel 4964: } else {
1.64 daniel 4965: n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
4966: if (n == NULL) return(NULL);
4967: n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
4968: cur->c2 = n;
4969: cur = n;
1.119 daniel 4970: xmlFree(elem);
1.61 daniel 4971: }
4972: SKIP_BLANKS;
4973: elem = xmlParseName(ctxt);
4974: if (elem == NULL) {
4975: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4976: ctxt->sax->error(ctxt->userData,
1.61 daniel 4977: "xmlParseElementMixedContentDecl : Name expected\n");
1.123 daniel 4978: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.61 daniel 4979: ctxt->wellFormed = 0;
4980: xmlFreeElementContent(cur);
4981: return(NULL);
4982: }
4983: SKIP_BLANKS;
1.97 daniel 4984: GROW;
1.61 daniel 4985: }
1.152 daniel 4986: if ((RAW == ')') && (NXT(1) == '*')) {
1.66 daniel 4987: if (elem != NULL) {
1.61 daniel 4988: cur->c2 = xmlNewElementContent(elem,
4989: XML_ELEMENT_CONTENT_ELEMENT);
1.119 daniel 4990: xmlFree(elem);
1.66 daniel 4991: }
1.65 daniel 4992: ret->ocur = XML_ELEMENT_CONTENT_MULT;
1.64 daniel 4993: SKIP(2);
1.61 daniel 4994: } else {
1.119 daniel 4995: if (elem != NULL) xmlFree(elem);
1.61 daniel 4996: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4997: ctxt->sax->error(ctxt->userData,
1.63 daniel 4998: "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
1.123 daniel 4999: ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
1.61 daniel 5000: ctxt->wellFormed = 0;
5001: xmlFreeElementContent(ret);
5002: return(NULL);
5003: }
5004:
5005: } else {
5006: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5007: ctxt->sax->error(ctxt->userData,
1.61 daniel 5008: "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
1.123 daniel 5009: ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
1.61 daniel 5010: ctxt->wellFormed = 0;
5011: }
5012: return(ret);
5013: }
5014:
5015: /**
5016: * xmlParseElementChildrenContentDecl:
1.50 daniel 5017: * @ctxt: an XML parser context
5018: *
1.61 daniel 5019: * parse the declaration for a Mixed Element content
5020: * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
1.22 daniel 5021: *
1.61 daniel 5022: *
1.22 daniel 5023: * [47] children ::= (choice | seq) ('?' | '*' | '+')?
5024: *
5025: * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
5026: *
5027: * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
5028: *
5029: * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
5030: *
1.99 daniel 5031: * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
5032: * TODO Parameter-entity replacement text must be properly nested
5033: * with parenthetized groups. That is to say, if either of the
5034: * opening or closing parentheses in a choice, seq, or Mixed
5035: * construct is contained in the replacement text for a parameter
5036: * entity, both must be contained in the same replacement text. For
5037: * interoperability, if a parameter-entity reference appears in a
5038: * choice, seq, or Mixed construct, its replacement text should not
5039: * be empty, and neither the first nor last non-blank character of
5040: * the replacement text should be a connector (| or ,).
5041: *
1.62 daniel 5042: * returns: the tree of xmlElementContentPtr describing the element
1.61 daniel 5043: * hierarchy.
5044: */
5045: xmlElementContentPtr
1.62 daniel 5046: xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
1.63 daniel 5047: xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
1.123 daniel 5048: xmlChar *elem;
5049: xmlChar type = 0;
1.62 daniel 5050:
5051: SKIP_BLANKS;
1.94 daniel 5052: GROW;
1.152 daniel 5053: if (RAW == '(') {
1.63 daniel 5054: /* Recurse on first child */
1.62 daniel 5055: NEXT;
5056: SKIP_BLANKS;
5057: cur = ret = xmlParseElementChildrenContentDecl(ctxt);
5058: SKIP_BLANKS;
1.101 daniel 5059: GROW;
1.62 daniel 5060: } else {
5061: elem = xmlParseName(ctxt);
5062: if (elem == NULL) {
5063: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5064: ctxt->sax->error(ctxt->userData,
1.62 daniel 5065: "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123 daniel 5066: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62 daniel 5067: ctxt->wellFormed = 0;
5068: return(NULL);
5069: }
5070: cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.101 daniel 5071: GROW;
1.152 daniel 5072: if (RAW == '?') {
1.104 daniel 5073: cur->ocur = XML_ELEMENT_CONTENT_OPT;
1.62 daniel 5074: NEXT;
1.152 daniel 5075: } else if (RAW == '*') {
1.104 daniel 5076: cur->ocur = XML_ELEMENT_CONTENT_MULT;
1.62 daniel 5077: NEXT;
1.152 daniel 5078: } else if (RAW == '+') {
1.104 daniel 5079: cur->ocur = XML_ELEMENT_CONTENT_PLUS;
1.62 daniel 5080: NEXT;
5081: } else {
1.104 daniel 5082: cur->ocur = XML_ELEMENT_CONTENT_ONCE;
1.62 daniel 5083: }
1.119 daniel 5084: xmlFree(elem);
1.101 daniel 5085: GROW;
1.62 daniel 5086: }
5087: SKIP_BLANKS;
1.91 daniel 5088: SHRINK;
1.152 daniel 5089: while (RAW != ')') {
1.63 daniel 5090: /*
5091: * Each loop we parse one separator and one element.
5092: */
1.152 daniel 5093: if (RAW == ',') {
1.62 daniel 5094: if (type == 0) type = CUR;
5095:
5096: /*
5097: * Detect "Name | Name , Name" error
5098: */
5099: else if (type != CUR) {
5100: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5101: ctxt->sax->error(ctxt->userData,
1.62 daniel 5102: "xmlParseElementChildrenContentDecl : '%c' expected\n",
5103: type);
1.123 daniel 5104: ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62 daniel 5105: ctxt->wellFormed = 0;
1.170 ! daniel 5106: if ((op != NULL) && (op != ret))
! 5107: xmlFreeElementContent(op);
! 5108: if ((last != NULL) && (last != ret))
! 5109: xmlFreeElementContent(last);
! 5110: if (ret != NULL)
! 5111: xmlFreeElementContent(ret);
1.62 daniel 5112: return(NULL);
5113: }
1.64 daniel 5114: NEXT;
1.62 daniel 5115:
1.63 daniel 5116: op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
5117: if (op == NULL) {
5118: xmlFreeElementContent(ret);
5119: return(NULL);
5120: }
5121: if (last == NULL) {
5122: op->c1 = ret;
1.65 daniel 5123: ret = cur = op;
1.63 daniel 5124: } else {
5125: cur->c2 = op;
5126: op->c1 = last;
5127: cur =op;
1.65 daniel 5128: last = NULL;
1.63 daniel 5129: }
1.152 daniel 5130: } else if (RAW == '|') {
1.62 daniel 5131: if (type == 0) type = CUR;
5132:
5133: /*
1.63 daniel 5134: * Detect "Name , Name | Name" error
1.62 daniel 5135: */
5136: else if (type != CUR) {
5137: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5138: ctxt->sax->error(ctxt->userData,
1.62 daniel 5139: "xmlParseElementChildrenContentDecl : '%c' expected\n",
5140: type);
1.123 daniel 5141: ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62 daniel 5142: ctxt->wellFormed = 0;
1.170 ! daniel 5143: if ((op != NULL) && (op != ret))
! 5144: xmlFreeElementContent(op);
! 5145: if ((last != NULL) && (last != ret))
! 5146: xmlFreeElementContent(last);
! 5147: if (ret != NULL)
! 5148: xmlFreeElementContent(ret);
1.62 daniel 5149: return(NULL);
5150: }
1.64 daniel 5151: NEXT;
1.62 daniel 5152:
1.63 daniel 5153: op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
5154: if (op == NULL) {
1.170 ! daniel 5155: if ((op != NULL) && (op != ret))
! 5156: xmlFreeElementContent(op);
! 5157: if ((last != NULL) && (last != ret))
! 5158: xmlFreeElementContent(last);
! 5159: if (ret != NULL)
! 5160: xmlFreeElementContent(ret);
1.63 daniel 5161: return(NULL);
5162: }
5163: if (last == NULL) {
5164: op->c1 = ret;
1.65 daniel 5165: ret = cur = op;
1.63 daniel 5166: } else {
5167: cur->c2 = op;
5168: op->c1 = last;
5169: cur =op;
1.65 daniel 5170: last = NULL;
1.63 daniel 5171: }
1.62 daniel 5172: } else {
5173: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5174: ctxt->sax->error(ctxt->userData,
1.62 daniel 5175: "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
5176: ctxt->wellFormed = 0;
1.123 daniel 5177: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
1.170 ! daniel 5178: if ((op != NULL) && (op != ret))
! 5179: xmlFreeElementContent(op);
! 5180: if ((last != NULL) && (last != ret))
! 5181: xmlFreeElementContent(last);
! 5182: if (ret != NULL)
! 5183: xmlFreeElementContent(ret);
1.62 daniel 5184: return(NULL);
5185: }
1.101 daniel 5186: GROW;
1.62 daniel 5187: SKIP_BLANKS;
1.101 daniel 5188: GROW;
1.152 daniel 5189: if (RAW == '(') {
1.63 daniel 5190: /* Recurse on second child */
1.62 daniel 5191: NEXT;
5192: SKIP_BLANKS;
1.65 daniel 5193: last = xmlParseElementChildrenContentDecl(ctxt);
1.62 daniel 5194: SKIP_BLANKS;
5195: } else {
5196: elem = xmlParseName(ctxt);
5197: if (elem == NULL) {
5198: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5199: ctxt->sax->error(ctxt->userData,
1.122 daniel 5200: "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123 daniel 5201: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62 daniel 5202: ctxt->wellFormed = 0;
1.170 ! daniel 5203: if ((op != NULL) && (op != ret))
! 5204: xmlFreeElementContent(op);
! 5205: if ((last != NULL) && (last != ret))
! 5206: xmlFreeElementContent(last);
! 5207: if (ret != NULL)
! 5208: xmlFreeElementContent(ret);
1.62 daniel 5209: return(NULL);
5210: }
1.65 daniel 5211: last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.119 daniel 5212: xmlFree(elem);
1.152 daniel 5213: if (RAW == '?') {
1.105 daniel 5214: last->ocur = XML_ELEMENT_CONTENT_OPT;
5215: NEXT;
1.152 daniel 5216: } else if (RAW == '*') {
1.105 daniel 5217: last->ocur = XML_ELEMENT_CONTENT_MULT;
5218: NEXT;
1.152 daniel 5219: } else if (RAW == '+') {
1.105 daniel 5220: last->ocur = XML_ELEMENT_CONTENT_PLUS;
5221: NEXT;
5222: } else {
5223: last->ocur = XML_ELEMENT_CONTENT_ONCE;
5224: }
1.63 daniel 5225: }
5226: SKIP_BLANKS;
1.97 daniel 5227: GROW;
1.64 daniel 5228: }
1.65 daniel 5229: if ((cur != NULL) && (last != NULL)) {
5230: cur->c2 = last;
1.62 daniel 5231: }
5232: NEXT;
1.152 daniel 5233: if (RAW == '?') {
1.62 daniel 5234: ret->ocur = XML_ELEMENT_CONTENT_OPT;
5235: NEXT;
1.152 daniel 5236: } else if (RAW == '*') {
1.62 daniel 5237: ret->ocur = XML_ELEMENT_CONTENT_MULT;
5238: NEXT;
1.152 daniel 5239: } else if (RAW == '+') {
1.62 daniel 5240: ret->ocur = XML_ELEMENT_CONTENT_PLUS;
5241: NEXT;
5242: }
5243: return(ret);
1.61 daniel 5244: }
5245:
5246: /**
5247: * xmlParseElementContentDecl:
5248: * @ctxt: an XML parser context
5249: * @name: the name of the element being defined.
5250: * @result: the Element Content pointer will be stored here if any
1.22 daniel 5251: *
1.61 daniel 5252: * parse the declaration for an Element content either Mixed or Children,
5253: * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
5254: *
5255: * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
1.50 daniel 5256: *
1.61 daniel 5257: * returns: the type of element content XML_ELEMENT_TYPE_xxx
1.22 daniel 5258: */
5259:
1.61 daniel 5260: int
1.123 daniel 5261: xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
1.61 daniel 5262: xmlElementContentPtr *result) {
5263:
5264: xmlElementContentPtr tree = NULL;
5265: int res;
5266:
5267: *result = NULL;
5268:
1.152 daniel 5269: if (RAW != '(') {
1.61 daniel 5270: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5271: ctxt->sax->error(ctxt->userData,
1.61 daniel 5272: "xmlParseElementContentDecl : '(' expected\n");
1.123 daniel 5273: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.61 daniel 5274: ctxt->wellFormed = 0;
5275: return(-1);
5276: }
5277: NEXT;
1.97 daniel 5278: GROW;
1.61 daniel 5279: SKIP_BLANKS;
1.152 daniel 5280: if ((RAW == '#') && (NXT(1) == 'P') &&
1.61 daniel 5281: (NXT(2) == 'C') && (NXT(3) == 'D') &&
5282: (NXT(4) == 'A') && (NXT(5) == 'T') &&
5283: (NXT(6) == 'A')) {
1.62 daniel 5284: tree = xmlParseElementMixedContentDecl(ctxt);
1.61 daniel 5285: res = XML_ELEMENT_TYPE_MIXED;
5286: } else {
1.62 daniel 5287: tree = xmlParseElementChildrenContentDecl(ctxt);
1.61 daniel 5288: res = XML_ELEMENT_TYPE_ELEMENT;
5289: }
5290: SKIP_BLANKS;
1.63 daniel 5291: /****************************
1.152 daniel 5292: if (RAW != ')') {
1.61 daniel 5293: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5294: ctxt->sax->error(ctxt->userData,
1.61 daniel 5295: "xmlParseElementContentDecl : ')' expected\n");
5296: ctxt->wellFormed = 0;
5297: return(-1);
5298: }
1.63 daniel 5299: ****************************/
5300: *result = tree;
1.61 daniel 5301: return(res);
1.22 daniel 5302: }
5303:
1.50 daniel 5304: /**
5305: * xmlParseElementDecl:
5306: * @ctxt: an XML parser context
5307: *
5308: * parse an Element declaration.
1.22 daniel 5309: *
5310: * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
5311: *
1.99 daniel 5312: * [ VC: Unique Element Type Declaration ]
1.117 daniel 5313: * No element type may be declared more than once
1.69 daniel 5314: *
5315: * Returns the type of the element, or -1 in case of error
1.22 daniel 5316: */
1.59 daniel 5317: int
1.55 daniel 5318: xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 5319: xmlChar *name;
1.59 daniel 5320: int ret = -1;
1.61 daniel 5321: xmlElementContentPtr content = NULL;
1.22 daniel 5322:
1.97 daniel 5323: GROW;
1.152 daniel 5324: if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 5325: (NXT(2) == 'E') && (NXT(3) == 'L') &&
5326: (NXT(4) == 'E') && (NXT(5) == 'M') &&
5327: (NXT(6) == 'E') && (NXT(7) == 'N') &&
1.59 daniel 5328: (NXT(8) == 'T')) {
1.40 daniel 5329: SKIP(9);
1.59 daniel 5330: if (!IS_BLANK(CUR)) {
5331: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5332: ctxt->sax->error(ctxt->userData,
1.59 daniel 5333: "Space required after 'ELEMENT'\n");
1.123 daniel 5334: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 5335: ctxt->wellFormed = 0;
5336: }
1.42 daniel 5337: SKIP_BLANKS;
1.22 daniel 5338: name = xmlParseName(ctxt);
5339: if (name == NULL) {
1.55 daniel 5340: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5341: ctxt->sax->error(ctxt->userData,
1.59 daniel 5342: "xmlParseElementDecl: no name for Element\n");
1.123 daniel 5343: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 5344: ctxt->wellFormed = 0;
5345: return(-1);
5346: }
5347: if (!IS_BLANK(CUR)) {
5348: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5349: ctxt->sax->error(ctxt->userData,
1.59 daniel 5350: "Space required after the element name\n");
1.123 daniel 5351: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 5352: ctxt->wellFormed = 0;
1.22 daniel 5353: }
1.42 daniel 5354: SKIP_BLANKS;
1.152 daniel 5355: if ((RAW == 'E') && (NXT(1) == 'M') &&
1.40 daniel 5356: (NXT(2) == 'P') && (NXT(3) == 'T') &&
5357: (NXT(4) == 'Y')) {
5358: SKIP(5);
1.22 daniel 5359: /*
5360: * Element must always be empty.
5361: */
1.59 daniel 5362: ret = XML_ELEMENT_TYPE_EMPTY;
1.152 daniel 5363: } else if ((RAW == 'A') && (NXT(1) == 'N') &&
1.40 daniel 5364: (NXT(2) == 'Y')) {
5365: SKIP(3);
1.22 daniel 5366: /*
5367: * Element is a generic container.
5368: */
1.59 daniel 5369: ret = XML_ELEMENT_TYPE_ANY;
1.152 daniel 5370: } else if (RAW == '(') {
1.61 daniel 5371: ret = xmlParseElementContentDecl(ctxt, name, &content);
1.22 daniel 5372: } else {
1.98 daniel 5373: /*
5374: * [ WFC: PEs in Internal Subset ] error handling.
5375: */
1.152 daniel 5376: if ((RAW == '%') && (ctxt->external == 0) &&
1.98 daniel 5377: (ctxt->inputNr == 1)) {
5378: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5379: ctxt->sax->error(ctxt->userData,
5380: "PEReference: forbidden within markup decl in internal subset\n");
1.123 daniel 5381: ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
1.98 daniel 5382: } else {
5383: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5384: ctxt->sax->error(ctxt->userData,
5385: "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
1.123 daniel 5386: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.98 daniel 5387: }
1.61 daniel 5388: ctxt->wellFormed = 0;
1.119 daniel 5389: if (name != NULL) xmlFree(name);
1.61 daniel 5390: return(-1);
1.22 daniel 5391: }
1.142 daniel 5392:
5393: SKIP_BLANKS;
5394: /*
5395: * Pop-up of finished entities.
5396: */
1.152 daniel 5397: while ((RAW == 0) && (ctxt->inputNr > 1))
1.142 daniel 5398: xmlPopInput(ctxt);
1.42 daniel 5399: SKIP_BLANKS;
1.142 daniel 5400:
1.152 daniel 5401: if (RAW != '>') {
1.55 daniel 5402: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5403: ctxt->sax->error(ctxt->userData,
1.31 daniel 5404: "xmlParseElementDecl: expected '>' at the end\n");
1.123 daniel 5405: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59 daniel 5406: ctxt->wellFormed = 0;
1.61 daniel 5407: } else {
1.40 daniel 5408: NEXT;
1.72 daniel 5409: if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
1.76 daniel 5410: ctxt->sax->elementDecl(ctxt->userData, name, ret,
5411: content);
1.61 daniel 5412: }
1.84 daniel 5413: if (content != NULL) {
5414: xmlFreeElementContent(content);
5415: }
1.61 daniel 5416: if (name != NULL) {
1.119 daniel 5417: xmlFree(name);
1.61 daniel 5418: }
1.22 daniel 5419: }
1.59 daniel 5420: return(ret);
1.22 daniel 5421: }
5422:
1.50 daniel 5423: /**
5424: * xmlParseMarkupDecl:
5425: * @ctxt: an XML parser context
5426: *
5427: * parse Markup declarations
1.22 daniel 5428: *
5429: * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
5430: * NotationDecl | PI | Comment
5431: *
1.98 daniel 5432: * [ VC: Proper Declaration/PE Nesting ]
5433: * TODO Parameter-entity replacement text must be properly nested with
5434: * markup declarations. That is to say, if either the first character
5435: * or the last character of a markup declaration (markupdecl above) is
5436: * contained in the replacement text for a parameter-entity reference,
5437: * both must be contained in the same replacement text.
5438: *
5439: * [ WFC: PEs in Internal Subset ]
5440: * In the internal DTD subset, parameter-entity references can occur
5441: * only where markup declarations can occur, not within markup declarations.
5442: * (This does not apply to references that occur in external parameter
5443: * entities or to the external subset.)
1.22 daniel 5444: */
1.55 daniel 5445: void
5446: xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
1.94 daniel 5447: GROW;
1.22 daniel 5448: xmlParseElementDecl(ctxt);
5449: xmlParseAttributeListDecl(ctxt);
5450: xmlParseEntityDecl(ctxt);
5451: xmlParseNotationDecl(ctxt);
5452: xmlParsePI(ctxt);
1.114 daniel 5453: xmlParseComment(ctxt);
1.98 daniel 5454: /*
5455: * This is only for internal subset. On external entities,
5456: * the replacement is done before parsing stage
5457: */
5458: if ((ctxt->external == 0) && (ctxt->inputNr == 1))
5459: xmlParsePEReference(ctxt);
1.97 daniel 5460: ctxt->instate = XML_PARSER_DTD;
1.22 daniel 5461: }
5462:
1.50 daniel 5463: /**
1.76 daniel 5464: * xmlParseTextDecl:
5465: * @ctxt: an XML parser context
5466: *
5467: * parse an XML declaration header for external entities
5468: *
5469: * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
5470: *
5471: * Returns the only valuable info for an external parsed entity, the encoding
5472: */
5473:
1.123 daniel 5474: xmlChar *
1.76 daniel 5475: xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 5476: xmlChar *version;
5477: xmlChar *encoding = NULL;
1.76 daniel 5478:
5479: /*
5480: * We know that '<?xml' is here.
5481: */
5482: SKIP(5);
5483:
5484: if (!IS_BLANK(CUR)) {
5485: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5486: ctxt->sax->error(ctxt->userData,
5487: "Space needed after '<?xml'\n");
1.123 daniel 5488: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76 daniel 5489: ctxt->wellFormed = 0;
5490: }
5491: SKIP_BLANKS;
5492:
5493: /*
5494: * We may have the VersionInfo here.
5495: */
5496: version = xmlParseVersionInfo(ctxt);
5497: if (version == NULL)
5498: version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.165 daniel 5499: ctxt->input->version = xmlStrdup(version);
1.119 daniel 5500: xmlFree(version);
1.76 daniel 5501:
5502: /*
5503: * We must have the encoding declaration
5504: */
5505: if (!IS_BLANK(CUR)) {
5506: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5507: ctxt->sax->error(ctxt->userData, "Space needed here\n");
1.123 daniel 5508: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76 daniel 5509: ctxt->wellFormed = 0;
5510: }
5511: encoding = xmlParseEncodingDecl(ctxt);
5512:
5513: SKIP_BLANKS;
1.152 daniel 5514: if ((RAW == '?') && (NXT(1) == '>')) {
1.76 daniel 5515: SKIP(2);
1.152 daniel 5516: } else if (RAW == '>') {
1.76 daniel 5517: /* Deprecated old WD ... */
5518: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5519: ctxt->sax->error(ctxt->userData,
5520: "XML declaration must end-up with '?>'\n");
1.123 daniel 5521: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76 daniel 5522: ctxt->wellFormed = 0;
5523: NEXT;
5524: } else {
5525: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5526: ctxt->sax->error(ctxt->userData,
5527: "parsing XML declaration: '?>' expected\n");
1.123 daniel 5528: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76 daniel 5529: ctxt->wellFormed = 0;
5530: MOVETO_ENDTAG(CUR_PTR);
5531: NEXT;
5532: }
5533: return(encoding);
5534: }
5535:
5536: /*
5537: * xmlParseConditionalSections
5538: * @ctxt: an XML parser context
5539: *
5540: * TODO : Conditionnal section are not yet supported !
5541: *
5542: * [61] conditionalSect ::= includeSect | ignoreSect
5543: * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
5544: * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
5545: * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
5546: * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
5547: */
5548:
5549: void
5550: xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
1.165 daniel 5551: SKIP(3);
5552: SKIP_BLANKS;
1.168 daniel 5553: if ((RAW == 'I') && (NXT(1) == 'N') && (NXT(2) == 'C') &&
5554: (NXT(3) == 'L') && (NXT(4) == 'U') && (NXT(5) == 'D') &&
5555: (NXT(6) == 'E')) {
1.165 daniel 5556: SKIP(7);
1.168 daniel 5557: SKIP_BLANKS;
5558: if (RAW != '[') {
5559: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5560: ctxt->sax->error(ctxt->userData,
5561: "XML conditional section '[' expected\n");
5562: ctxt->errNo = XML_ERR_CONDSEC_INVALID;
5563: ctxt->wellFormed = 0;
5564: } else {
5565: NEXT;
5566: }
1.165 daniel 5567: while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
5568: (NXT(2) != '>'))) {
5569: const xmlChar *check = CUR_PTR;
5570: int cons = ctxt->input->consumed;
5571: int tok = ctxt->token;
5572:
5573: if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
5574: xmlParseConditionalSections(ctxt);
5575: } else if (IS_BLANK(CUR)) {
5576: NEXT;
5577: } else if (RAW == '%') {
5578: xmlParsePEReference(ctxt);
5579: } else
5580: xmlParseMarkupDecl(ctxt);
5581:
5582: /*
5583: * Pop-up of finished entities.
5584: */
5585: while ((RAW == 0) && (ctxt->inputNr > 1))
5586: xmlPopInput(ctxt);
5587:
5588: if ((CUR_PTR == check) && (cons == ctxt->input->consumed) &&
5589: (tok == ctxt->token)) {
5590: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5591: ctxt->sax->error(ctxt->userData,
5592: "Content error in the external subset\n");
5593: ctxt->wellFormed = 0;
5594: ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
5595: break;
5596: }
5597: }
1.168 daniel 5598: } else if ((RAW == 'I') && (NXT(1) == 'G') && (NXT(2) == 'N') &&
5599: (NXT(3) == 'O') && (NXT(4) == 'R') && (NXT(5) == 'E')) {
5600: SKIP(6);
5601: SKIP_BLANKS;
5602: if (RAW != '[') {
5603: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5604: ctxt->sax->error(ctxt->userData,
5605: "XML conditional section '[' expected\n");
5606: ctxt->errNo = XML_ERR_CONDSEC_INVALID;
5607: ctxt->wellFormed = 0;
5608: } else {
5609: NEXT;
5610: }
1.143 daniel 5611: /*
1.165 daniel 5612: * Skip up to the end of the conditionnal section.
1.168 daniel 5613: * !!!! TODO [4.3] Note that for reliable parsing, the contents
5614: * of even ignored conditional sections must be read in order to
5615: * detect nested conditional sections
1.143 daniel 5616: */
1.165 daniel 5617: while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
5618: (NXT(2) != '>'))) {
5619: NEXT;
5620: /*
5621: * Pop-up of finished entities.
5622: */
5623: while ((RAW == 0) && (ctxt->inputNr > 1))
5624: xmlPopInput(ctxt);
1.143 daniel 5625:
1.165 daniel 5626: if (RAW == 0)
5627: GROW;
5628: }
1.168 daniel 5629: } else {
5630: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5631: ctxt->sax->error(ctxt->userData,
5632: "XML conditional section INCLUDE or IGNORE keyword expected\n");
5633: ctxt->errNo = XML_ERR_CONDSEC_INVALID;
5634: ctxt->wellFormed = 0;
1.143 daniel 5635: }
5636:
1.152 daniel 5637: if (RAW == 0)
1.143 daniel 5638: SHRINK;
5639:
1.152 daniel 5640: if (RAW == 0) {
1.76 daniel 5641: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5642: ctxt->sax->error(ctxt->userData,
5643: "XML conditional section not closed\n");
1.123 daniel 5644: ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
1.76 daniel 5645: ctxt->wellFormed = 0;
1.143 daniel 5646: } else {
5647: SKIP(3);
1.76 daniel 5648: }
5649: }
5650:
5651: /**
1.124 daniel 5652: * xmlParseExternalSubset:
1.76 daniel 5653: * @ctxt: an XML parser context
1.124 daniel 5654: * @ExternalID: the external identifier
5655: * @SystemID: the system identifier (or URL)
1.76 daniel 5656: *
5657: * parse Markup declarations from an external subset
5658: *
5659: * [30] extSubset ::= textDecl? extSubsetDecl
5660: *
5661: * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
5662: */
5663: void
1.123 daniel 5664: xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
5665: const xmlChar *SystemID) {
1.132 daniel 5666: GROW;
1.152 daniel 5667: if ((RAW == '<') && (NXT(1) == '?') &&
1.76 daniel 5668: (NXT(2) == 'x') && (NXT(3) == 'm') &&
5669: (NXT(4) == 'l')) {
1.134 daniel 5670: xmlChar *decl;
5671:
5672: decl = xmlParseTextDecl(ctxt);
5673: if (decl != NULL)
5674: xmlFree(decl);
1.76 daniel 5675: }
1.79 daniel 5676: if (ctxt->myDoc == NULL) {
1.116 daniel 5677: ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
1.79 daniel 5678: }
5679: if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
5680: xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
5681:
1.96 daniel 5682: ctxt->instate = XML_PARSER_DTD;
1.101 daniel 5683: ctxt->external = 1;
1.152 daniel 5684: while (((RAW == '<') && (NXT(1) == '?')) ||
5685: ((RAW == '<') && (NXT(1) == '!')) ||
1.164 daniel 5686: IS_BLANK(CUR)) {
1.123 daniel 5687: const xmlChar *check = CUR_PTR;
1.115 daniel 5688: int cons = ctxt->input->consumed;
1.164 daniel 5689: int tok = ctxt->token;
1.115 daniel 5690:
1.152 daniel 5691: if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
1.76 daniel 5692: xmlParseConditionalSections(ctxt);
5693: } else if (IS_BLANK(CUR)) {
5694: NEXT;
1.152 daniel 5695: } else if (RAW == '%') {
1.76 daniel 5696: xmlParsePEReference(ctxt);
5697: } else
5698: xmlParseMarkupDecl(ctxt);
1.77 daniel 5699:
5700: /*
5701: * Pop-up of finished entities.
5702: */
1.166 daniel 5703: while ((RAW == 0) && (ctxt->inputNr > 1))
1.77 daniel 5704: xmlPopInput(ctxt);
5705:
1.164 daniel 5706: if ((CUR_PTR == check) && (cons == ctxt->input->consumed) &&
5707: (tok == ctxt->token)) {
1.115 daniel 5708: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5709: ctxt->sax->error(ctxt->userData,
5710: "Content error in the external subset\n");
5711: ctxt->wellFormed = 0;
1.123 daniel 5712: ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.115 daniel 5713: break;
5714: }
1.76 daniel 5715: }
5716:
1.152 daniel 5717: if (RAW != 0) {
1.76 daniel 5718: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5719: ctxt->sax->error(ctxt->userData,
5720: "Extra content at the end of the document\n");
1.123 daniel 5721: ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.76 daniel 5722: ctxt->wellFormed = 0;
5723: }
5724:
5725: }
5726:
5727: /**
1.77 daniel 5728: * xmlParseReference:
5729: * @ctxt: an XML parser context
5730: *
5731: * parse and handle entity references in content, depending on the SAX
5732: * interface, this may end-up in a call to character() if this is a
1.79 daniel 5733: * CharRef, a predefined entity, if there is no reference() callback.
5734: * or if the parser was asked to switch to that mode.
1.77 daniel 5735: *
5736: * [67] Reference ::= EntityRef | CharRef
5737: */
5738: void
5739: xmlParseReference(xmlParserCtxtPtr ctxt) {
5740: xmlEntityPtr ent;
1.123 daniel 5741: xmlChar *val;
1.152 daniel 5742: if (RAW != '&') return;
1.77 daniel 5743:
1.113 daniel 5744: if (ctxt->inputNr > 1) {
1.123 daniel 5745: xmlChar cur[2] = { '&' , 0 } ;
1.113 daniel 5746:
5747: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
5748: ctxt->sax->characters(ctxt->userData, cur, 1);
5749: if (ctxt->token == '&')
5750: ctxt->token = 0;
5751: else {
5752: SKIP(1);
5753: }
5754: return;
5755: }
1.77 daniel 5756: if (NXT(1) == '#') {
1.152 daniel 5757: int i = 0;
1.153 daniel 5758: xmlChar out[10];
5759: int hex = NXT(2);
1.77 daniel 5760: int val = xmlParseCharRef(ctxt);
1.152 daniel 5761:
1.153 daniel 5762: if (ctxt->encoding != NULL) {
5763: /*
5764: * So we are using non-UTF-8 buffers
5765: * Check that the char fit on 8bits, if not
5766: * generate a CharRef.
5767: */
5768: if (val <= 0xFF) {
5769: out[0] = val;
5770: out[1] = 0;
5771: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
5772: ctxt->sax->characters(ctxt->userData, out, 1);
5773: } else {
5774: if ((hex == 'x') || (hex == 'X'))
5775: sprintf((char *)out, "#x%X", val);
5776: else
5777: sprintf((char *)out, "#%d", val);
5778: if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL))
5779: ctxt->sax->reference(ctxt->userData, out);
5780: }
5781: } else {
5782: /*
5783: * Just encode the value in UTF-8
5784: */
5785: COPY_BUF(0 ,out, i, val);
5786: out[i] = 0;
5787: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
5788: ctxt->sax->characters(ctxt->userData, out, i);
5789: }
1.77 daniel 5790: } else {
5791: ent = xmlParseEntityRef(ctxt);
5792: if (ent == NULL) return;
5793: if ((ent->name != NULL) &&
1.159 daniel 5794: (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
1.113 daniel 5795: if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
5796: (ctxt->replaceEntities == 0)) {
5797: /*
5798: * Create a node.
5799: */
5800: ctxt->sax->reference(ctxt->userData, ent->name);
5801: return;
5802: } else if (ctxt->replaceEntities) {
5803: xmlParserInputPtr input;
1.79 daniel 5804:
1.113 daniel 5805: input = xmlNewEntityInputStream(ctxt, ent);
5806: xmlPushInput(ctxt, input);
1.167 daniel 5807: if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) &&
5808: (RAW == '<') && (NXT(1) == '?') &&
5809: (NXT(2) == 'x') && (NXT(3) == 'm') &&
5810: (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
5811: xmlParseXMLDecl(ctxt);
5812: if (input->standalone) {
5813: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5814: ctxt->sax->error(ctxt->userData,
5815: "external parsed entities cannot be standalone\n");
5816: ctxt->errNo = XML_ERR_EXT_ENTITY_STANDALONE;
5817: ctxt->wellFormed = 0;
5818: }
5819: }
1.113 daniel 5820: return;
5821: }
1.77 daniel 5822: }
5823: val = ent->content;
5824: if (val == NULL) return;
5825: /*
5826: * inline the entity.
5827: */
5828: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
5829: ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
5830: }
1.24 daniel 5831: }
5832:
1.50 daniel 5833: /**
5834: * xmlParseEntityRef:
5835: * @ctxt: an XML parser context
5836: *
5837: * parse ENTITY references declarations
1.24 daniel 5838: *
5839: * [68] EntityRef ::= '&' Name ';'
1.68 daniel 5840: *
1.98 daniel 5841: * [ WFC: Entity Declared ]
5842: * In a document without any DTD, a document with only an internal DTD
5843: * subset which contains no parameter entity references, or a document
5844: * with "standalone='yes'", the Name given in the entity reference
5845: * must match that in an entity declaration, except that well-formed
5846: * documents need not declare any of the following entities: amp, lt,
5847: * gt, apos, quot. The declaration of a parameter entity must precede
5848: * any reference to it. Similarly, the declaration of a general entity
5849: * must precede any reference to it which appears in a default value in an
5850: * attribute-list declaration. Note that if entities are declared in the
5851: * external subset or in external parameter entities, a non-validating
5852: * processor is not obligated to read and process their declarations;
5853: * for such documents, the rule that an entity must be declared is a
5854: * well-formedness constraint only if standalone='yes'.
5855: *
5856: * [ WFC: Parsed Entity ]
5857: * An entity reference must not contain the name of an unparsed entity
5858: *
1.77 daniel 5859: * Returns the xmlEntityPtr if found, or NULL otherwise.
1.24 daniel 5860: */
1.77 daniel 5861: xmlEntityPtr
1.55 daniel 5862: xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
1.123 daniel 5863: xmlChar *name;
1.72 daniel 5864: xmlEntityPtr ent = NULL;
1.24 daniel 5865:
1.91 daniel 5866: GROW;
1.111 daniel 5867:
1.152 daniel 5868: if (RAW == '&') {
1.40 daniel 5869: NEXT;
1.24 daniel 5870: name = xmlParseName(ctxt);
5871: if (name == NULL) {
1.55 daniel 5872: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 5873: ctxt->sax->error(ctxt->userData,
5874: "xmlParseEntityRef: no name\n");
1.123 daniel 5875: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 5876: ctxt->wellFormed = 0;
1.24 daniel 5877: } else {
1.152 daniel 5878: if (RAW == ';') {
1.40 daniel 5879: NEXT;
1.24 daniel 5880: /*
1.77 daniel 5881: * Ask first SAX for entity resolution, otherwise try the
5882: * predefined set.
5883: */
5884: if (ctxt->sax != NULL) {
5885: if (ctxt->sax->getEntity != NULL)
5886: ent = ctxt->sax->getEntity(ctxt->userData, name);
5887: if (ent == NULL)
5888: ent = xmlGetPredefinedEntity(name);
5889: }
5890: /*
1.98 daniel 5891: * [ WFC: Entity Declared ]
5892: * In a document without any DTD, a document with only an
5893: * internal DTD subset which contains no parameter entity
5894: * references, or a document with "standalone='yes'", the
5895: * Name given in the entity reference must match that in an
5896: * entity declaration, except that well-formed documents
5897: * need not declare any of the following entities: amp, lt,
5898: * gt, apos, quot.
5899: * The declaration of a parameter entity must precede any
5900: * reference to it.
5901: * Similarly, the declaration of a general entity must
5902: * precede any reference to it which appears in a default
5903: * value in an attribute-list declaration. Note that if
5904: * entities are declared in the external subset or in
5905: * external parameter entities, a non-validating processor
5906: * is not obligated to read and process their declarations;
5907: * for such documents, the rule that an entity must be
5908: * declared is a well-formedness constraint only if
5909: * standalone='yes'.
1.59 daniel 5910: */
1.77 daniel 5911: if (ent == NULL) {
1.98 daniel 5912: if ((ctxt->standalone == 1) ||
5913: ((ctxt->hasExternalSubset == 0) &&
5914: (ctxt->hasPErefs == 0))) {
5915: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77 daniel 5916: ctxt->sax->error(ctxt->userData,
5917: "Entity '%s' not defined\n", name);
1.123 daniel 5918: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.77 daniel 5919: ctxt->wellFormed = 0;
5920: } else {
1.98 daniel 5921: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5922: ctxt->sax->warning(ctxt->userData,
5923: "Entity '%s' not defined\n", name);
1.123 daniel 5924: ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
1.59 daniel 5925: }
1.77 daniel 5926: }
1.59 daniel 5927:
5928: /*
1.98 daniel 5929: * [ WFC: Parsed Entity ]
5930: * An entity reference must not contain the name of an
5931: * unparsed entity
5932: */
1.159 daniel 5933: else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1.98 daniel 5934: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5935: ctxt->sax->error(ctxt->userData,
5936: "Entity reference to unparsed entity %s\n", name);
1.123 daniel 5937: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98 daniel 5938: ctxt->wellFormed = 0;
5939: }
5940:
5941: /*
5942: * [ WFC: No External Entity References ]
5943: * Attribute values cannot contain direct or indirect
5944: * entity references to external entities.
5945: */
5946: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
1.159 daniel 5947: (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
1.98 daniel 5948: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5949: ctxt->sax->error(ctxt->userData,
5950: "Attribute references external entity '%s'\n", name);
1.123 daniel 5951: ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
1.98 daniel 5952: ctxt->wellFormed = 0;
5953: }
5954: /*
5955: * [ WFC: No < in Attribute Values ]
5956: * The replacement text of any entity referred to directly or
5957: * indirectly in an attribute value (other than "<") must
5958: * not contain a <.
1.59 daniel 5959: */
1.98 daniel 5960: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
1.116 daniel 5961: (ent != NULL) &&
5962: (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
1.98 daniel 5963: (ent->content != NULL) &&
5964: (xmlStrchr(ent->content, '<'))) {
5965: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5966: ctxt->sax->error(ctxt->userData,
5967: "'<' in entity '%s' is not allowed in attributes values\n", name);
1.123 daniel 5968: ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
1.98 daniel 5969: ctxt->wellFormed = 0;
5970: }
5971:
5972: /*
5973: * Internal check, no parameter entities here ...
5974: */
5975: else {
1.159 daniel 5976: switch (ent->etype) {
1.59 daniel 5977: case XML_INTERNAL_PARAMETER_ENTITY:
5978: case XML_EXTERNAL_PARAMETER_ENTITY:
5979: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5980: ctxt->sax->error(ctxt->userData,
1.59 daniel 5981: "Attempt to reference the parameter entity '%s'\n", name);
1.123 daniel 5982: ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
1.59 daniel 5983: ctxt->wellFormed = 0;
5984: break;
5985: }
5986: }
5987:
5988: /*
1.98 daniel 5989: * [ WFC: No Recursion ]
1.117 daniel 5990: * TODO A parsed entity must not contain a recursive reference
5991: * to itself, either directly or indirectly.
1.59 daniel 5992: */
1.77 daniel 5993:
1.24 daniel 5994: } else {
1.55 daniel 5995: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5996: ctxt->sax->error(ctxt->userData,
1.59 daniel 5997: "xmlParseEntityRef: expecting ';'\n");
1.123 daniel 5998: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59 daniel 5999: ctxt->wellFormed = 0;
1.24 daniel 6000: }
1.119 daniel 6001: xmlFree(name);
1.24 daniel 6002: }
6003: }
1.77 daniel 6004: return(ent);
1.24 daniel 6005: }
1.135 daniel 6006: /**
6007: * xmlParseStringEntityRef:
6008: * @ctxt: an XML parser context
6009: * @str: a pointer to an index in the string
6010: *
6011: * parse ENTITY references declarations, but this version parses it from
6012: * a string value.
6013: *
6014: * [68] EntityRef ::= '&' Name ';'
6015: *
6016: * [ WFC: Entity Declared ]
6017: * In a document without any DTD, a document with only an internal DTD
6018: * subset which contains no parameter entity references, or a document
6019: * with "standalone='yes'", the Name given in the entity reference
6020: * must match that in an entity declaration, except that well-formed
6021: * documents need not declare any of the following entities: amp, lt,
6022: * gt, apos, quot. The declaration of a parameter entity must precede
6023: * any reference to it. Similarly, the declaration of a general entity
6024: * must precede any reference to it which appears in a default value in an
6025: * attribute-list declaration. Note that if entities are declared in the
6026: * external subset or in external parameter entities, a non-validating
6027: * processor is not obligated to read and process their declarations;
6028: * for such documents, the rule that an entity must be declared is a
6029: * well-formedness constraint only if standalone='yes'.
6030: *
6031: * [ WFC: Parsed Entity ]
6032: * An entity reference must not contain the name of an unparsed entity
6033: *
6034: * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
6035: * is updated to the current location in the string.
6036: */
6037: xmlEntityPtr
6038: xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
6039: xmlChar *name;
6040: const xmlChar *ptr;
6041: xmlChar cur;
6042: xmlEntityPtr ent = NULL;
6043:
6044: GROW;
6045:
1.156 daniel 6046: if ((str == NULL) || (*str == NULL))
6047: return(NULL);
1.135 daniel 6048: ptr = *str;
6049: cur = *ptr;
6050: if (cur == '&') {
6051: ptr++;
6052: cur = *ptr;
6053: name = xmlParseStringName(ctxt, &ptr);
6054: if (name == NULL) {
6055: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6056: ctxt->sax->error(ctxt->userData,
6057: "xmlParseEntityRef: no name\n");
6058: ctxt->errNo = XML_ERR_NAME_REQUIRED;
6059: ctxt->wellFormed = 0;
6060: } else {
1.152 daniel 6061: if (RAW == ';') {
1.135 daniel 6062: NEXT;
6063: /*
6064: * Ask first SAX for entity resolution, otherwise try the
6065: * predefined set.
6066: */
6067: if (ctxt->sax != NULL) {
6068: if (ctxt->sax->getEntity != NULL)
6069: ent = ctxt->sax->getEntity(ctxt->userData, name);
6070: if (ent == NULL)
6071: ent = xmlGetPredefinedEntity(name);
6072: }
6073: /*
6074: * [ WFC: Entity Declared ]
6075: * In a document without any DTD, a document with only an
6076: * internal DTD subset which contains no parameter entity
6077: * references, or a document with "standalone='yes'", the
6078: * Name given in the entity reference must match that in an
6079: * entity declaration, except that well-formed documents
6080: * need not declare any of the following entities: amp, lt,
6081: * gt, apos, quot.
6082: * The declaration of a parameter entity must precede any
6083: * reference to it.
6084: * Similarly, the declaration of a general entity must
6085: * precede any reference to it which appears in a default
6086: * value in an attribute-list declaration. Note that if
6087: * entities are declared in the external subset or in
6088: * external parameter entities, a non-validating processor
6089: * is not obligated to read and process their declarations;
6090: * for such documents, the rule that an entity must be
6091: * declared is a well-formedness constraint only if
6092: * standalone='yes'.
6093: */
6094: if (ent == NULL) {
6095: if ((ctxt->standalone == 1) ||
6096: ((ctxt->hasExternalSubset == 0) &&
6097: (ctxt->hasPErefs == 0))) {
6098: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6099: ctxt->sax->error(ctxt->userData,
6100: "Entity '%s' not defined\n", name);
6101: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
6102: ctxt->wellFormed = 0;
6103: } else {
6104: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
6105: ctxt->sax->warning(ctxt->userData,
6106: "Entity '%s' not defined\n", name);
6107: ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
6108: }
6109: }
6110:
6111: /*
6112: * [ WFC: Parsed Entity ]
6113: * An entity reference must not contain the name of an
6114: * unparsed entity
6115: */
1.159 daniel 6116: else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1.135 daniel 6117: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6118: ctxt->sax->error(ctxt->userData,
6119: "Entity reference to unparsed entity %s\n", name);
6120: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
6121: ctxt->wellFormed = 0;
6122: }
6123:
6124: /*
6125: * [ WFC: No External Entity References ]
6126: * Attribute values cannot contain direct or indirect
6127: * entity references to external entities.
6128: */
6129: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
1.159 daniel 6130: (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
1.135 daniel 6131: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6132: ctxt->sax->error(ctxt->userData,
6133: "Attribute references external entity '%s'\n", name);
6134: ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
6135: ctxt->wellFormed = 0;
6136: }
6137: /*
6138: * [ WFC: No < in Attribute Values ]
6139: * The replacement text of any entity referred to directly or
6140: * indirectly in an attribute value (other than "<") must
6141: * not contain a <.
6142: */
6143: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
6144: (ent != NULL) &&
6145: (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
6146: (ent->content != NULL) &&
6147: (xmlStrchr(ent->content, '<'))) {
6148: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6149: ctxt->sax->error(ctxt->userData,
6150: "'<' in entity '%s' is not allowed in attributes values\n", name);
6151: ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
6152: ctxt->wellFormed = 0;
6153: }
6154:
6155: /*
6156: * Internal check, no parameter entities here ...
6157: */
6158: else {
1.159 daniel 6159: switch (ent->etype) {
1.135 daniel 6160: case XML_INTERNAL_PARAMETER_ENTITY:
6161: case XML_EXTERNAL_PARAMETER_ENTITY:
6162: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6163: ctxt->sax->error(ctxt->userData,
6164: "Attempt to reference the parameter entity '%s'\n", name);
6165: ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
6166: ctxt->wellFormed = 0;
6167: break;
6168: }
6169: }
6170:
6171: /*
6172: * [ WFC: No Recursion ]
6173: * TODO A parsed entity must not contain a recursive reference
6174: * to itself, either directly or indirectly.
6175: */
6176:
6177: } else {
6178: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6179: ctxt->sax->error(ctxt->userData,
6180: "xmlParseEntityRef: expecting ';'\n");
6181: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
6182: ctxt->wellFormed = 0;
6183: }
6184: xmlFree(name);
6185: }
6186: }
6187: return(ent);
6188: }
1.24 daniel 6189:
1.50 daniel 6190: /**
6191: * xmlParsePEReference:
6192: * @ctxt: an XML parser context
6193: *
6194: * parse PEReference declarations
1.77 daniel 6195: * The entity content is handled directly by pushing it's content as
6196: * a new input stream.
1.22 daniel 6197: *
6198: * [69] PEReference ::= '%' Name ';'
1.68 daniel 6199: *
1.98 daniel 6200: * [ WFC: No Recursion ]
6201: * TODO A parsed entity must not contain a recursive
6202: * reference to itself, either directly or indirectly.
6203: *
6204: * [ WFC: Entity Declared ]
6205: * In a document without any DTD, a document with only an internal DTD
6206: * subset which contains no parameter entity references, or a document
6207: * with "standalone='yes'", ... ... The declaration of a parameter
6208: * entity must precede any reference to it...
6209: *
6210: * [ VC: Entity Declared ]
6211: * In a document with an external subset or external parameter entities
6212: * with "standalone='no'", ... ... The declaration of a parameter entity
6213: * must precede any reference to it...
6214: *
6215: * [ WFC: In DTD ]
6216: * Parameter-entity references may only appear in the DTD.
6217: * NOTE: misleading but this is handled.
1.22 daniel 6218: */
1.77 daniel 6219: void
1.55 daniel 6220: xmlParsePEReference(xmlParserCtxtPtr ctxt) {
1.123 daniel 6221: xmlChar *name;
1.72 daniel 6222: xmlEntityPtr entity = NULL;
1.50 daniel 6223: xmlParserInputPtr input;
1.22 daniel 6224:
1.152 daniel 6225: if (RAW == '%') {
1.40 daniel 6226: NEXT;
1.22 daniel 6227: name = xmlParseName(ctxt);
6228: if (name == NULL) {
1.55 daniel 6229: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 6230: ctxt->sax->error(ctxt->userData,
6231: "xmlParsePEReference: no name\n");
1.123 daniel 6232: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 6233: ctxt->wellFormed = 0;
1.22 daniel 6234: } else {
1.152 daniel 6235: if (RAW == ';') {
1.40 daniel 6236: NEXT;
1.98 daniel 6237: if ((ctxt->sax != NULL) &&
6238: (ctxt->sax->getParameterEntity != NULL))
6239: entity = ctxt->sax->getParameterEntity(ctxt->userData,
6240: name);
1.45 daniel 6241: if (entity == NULL) {
1.98 daniel 6242: /*
6243: * [ WFC: Entity Declared ]
6244: * In a document without any DTD, a document with only an
6245: * internal DTD subset which contains no parameter entity
6246: * references, or a document with "standalone='yes'", ...
6247: * ... The declaration of a parameter entity must precede
6248: * any reference to it...
6249: */
6250: if ((ctxt->standalone == 1) ||
6251: ((ctxt->hasExternalSubset == 0) &&
6252: (ctxt->hasPErefs == 0))) {
6253: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6254: ctxt->sax->error(ctxt->userData,
6255: "PEReference: %%%s; not found\n", name);
1.123 daniel 6256: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.98 daniel 6257: ctxt->wellFormed = 0;
6258: } else {
6259: /*
6260: * [ VC: Entity Declared ]
6261: * In a document with an external subset or external
6262: * parameter entities with "standalone='no'", ...
6263: * ... The declaration of a parameter entity must precede
6264: * any reference to it...
6265: */
6266: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
6267: ctxt->sax->warning(ctxt->userData,
6268: "PEReference: %%%s; not found\n", name);
6269: ctxt->valid = 0;
6270: }
1.50 daniel 6271: } else {
1.98 daniel 6272: /*
6273: * Internal checking in case the entity quest barfed
6274: */
1.159 daniel 6275: if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
6276: (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
1.98 daniel 6277: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
6278: ctxt->sax->warning(ctxt->userData,
6279: "Internal: %%%s; is not a parameter entity\n", name);
6280: } else {
1.164 daniel 6281: /*
6282: * TODO !!!
6283: * handle the extra spaces added before and after
6284: * c.f. http://www.w3.org/TR/REC-xml#as-PE
6285: */
1.98 daniel 6286: input = xmlNewEntityInputStream(ctxt, entity);
6287: xmlPushInput(ctxt, input);
1.164 daniel 6288: if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
6289: (RAW == '<') && (NXT(1) == '?') &&
6290: (NXT(2) == 'x') && (NXT(3) == 'm') &&
6291: (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
6292: xmlParseXMLDecl(ctxt);
6293: }
6294: if (ctxt->token == 0)
6295: ctxt->token = ' ';
1.98 daniel 6296: }
1.45 daniel 6297: }
1.98 daniel 6298: ctxt->hasPErefs = 1;
1.22 daniel 6299: } else {
1.55 daniel 6300: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6301: ctxt->sax->error(ctxt->userData,
1.59 daniel 6302: "xmlParsePEReference: expecting ';'\n");
1.123 daniel 6303: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59 daniel 6304: ctxt->wellFormed = 0;
1.22 daniel 6305: }
1.119 daniel 6306: xmlFree(name);
1.3 veillard 6307: }
6308: }
6309: }
6310:
1.50 daniel 6311: /**
1.135 daniel 6312: * xmlParseStringPEReference:
6313: * @ctxt: an XML parser context
6314: * @str: a pointer to an index in the string
6315: *
6316: * parse PEReference declarations
6317: *
6318: * [69] PEReference ::= '%' Name ';'
6319: *
6320: * [ WFC: No Recursion ]
6321: * TODO A parsed entity must not contain a recursive
6322: * reference to itself, either directly or indirectly.
6323: *
6324: * [ WFC: Entity Declared ]
6325: * In a document without any DTD, a document with only an internal DTD
6326: * subset which contains no parameter entity references, or a document
6327: * with "standalone='yes'", ... ... The declaration of a parameter
6328: * entity must precede any reference to it...
6329: *
6330: * [ VC: Entity Declared ]
6331: * In a document with an external subset or external parameter entities
6332: * with "standalone='no'", ... ... The declaration of a parameter entity
6333: * must precede any reference to it...
6334: *
6335: * [ WFC: In DTD ]
6336: * Parameter-entity references may only appear in the DTD.
6337: * NOTE: misleading but this is handled.
6338: *
6339: * Returns the string of the entity content.
6340: * str is updated to the current value of the index
6341: */
6342: xmlEntityPtr
6343: xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
6344: const xmlChar *ptr;
6345: xmlChar cur;
6346: xmlChar *name;
6347: xmlEntityPtr entity = NULL;
6348:
6349: if ((str == NULL) || (*str == NULL)) return(NULL);
6350: ptr = *str;
6351: cur = *ptr;
6352: if (cur == '%') {
6353: ptr++;
6354: cur = *ptr;
6355: name = xmlParseStringName(ctxt, &ptr);
6356: if (name == NULL) {
6357: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6358: ctxt->sax->error(ctxt->userData,
6359: "xmlParseStringPEReference: no name\n");
6360: ctxt->errNo = XML_ERR_NAME_REQUIRED;
6361: ctxt->wellFormed = 0;
6362: } else {
6363: cur = *ptr;
6364: if (cur == ';') {
6365: ptr++;
6366: cur = *ptr;
6367: if ((ctxt->sax != NULL) &&
6368: (ctxt->sax->getParameterEntity != NULL))
6369: entity = ctxt->sax->getParameterEntity(ctxt->userData,
6370: name);
6371: if (entity == NULL) {
6372: /*
6373: * [ WFC: Entity Declared ]
6374: * In a document without any DTD, a document with only an
6375: * internal DTD subset which contains no parameter entity
6376: * references, or a document with "standalone='yes'", ...
6377: * ... The declaration of a parameter entity must precede
6378: * any reference to it...
6379: */
6380: if ((ctxt->standalone == 1) ||
6381: ((ctxt->hasExternalSubset == 0) &&
6382: (ctxt->hasPErefs == 0))) {
6383: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6384: ctxt->sax->error(ctxt->userData,
6385: "PEReference: %%%s; not found\n", name);
6386: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
6387: ctxt->wellFormed = 0;
6388: } else {
6389: /*
6390: * [ VC: Entity Declared ]
6391: * In a document with an external subset or external
6392: * parameter entities with "standalone='no'", ...
6393: * ... The declaration of a parameter entity must
6394: * precede any reference to it...
6395: */
6396: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
6397: ctxt->sax->warning(ctxt->userData,
6398: "PEReference: %%%s; not found\n", name);
6399: ctxt->valid = 0;
6400: }
6401: } else {
6402: /*
6403: * Internal checking in case the entity quest barfed
6404: */
1.159 daniel 6405: if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
6406: (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
1.135 daniel 6407: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
6408: ctxt->sax->warning(ctxt->userData,
6409: "Internal: %%%s; is not a parameter entity\n", name);
6410: }
6411: }
6412: ctxt->hasPErefs = 1;
6413: } else {
6414: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6415: ctxt->sax->error(ctxt->userData,
6416: "xmlParseStringPEReference: expecting ';'\n");
6417: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
6418: ctxt->wellFormed = 0;
6419: }
6420: xmlFree(name);
6421: }
6422: }
6423: *str = ptr;
6424: return(entity);
6425: }
6426:
6427: /**
1.50 daniel 6428: * xmlParseDocTypeDecl :
6429: * @ctxt: an XML parser context
6430: *
6431: * parse a DOCTYPE declaration
1.21 daniel 6432: *
1.22 daniel 6433: * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
6434: * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
1.98 daniel 6435: *
6436: * [ VC: Root Element Type ]
1.99 daniel 6437: * The Name in the document type declaration must match the element
1.98 daniel 6438: * type of the root element.
1.21 daniel 6439: */
6440:
1.55 daniel 6441: void
6442: xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
1.165 daniel 6443: xmlChar *name = NULL;
1.123 daniel 6444: xmlChar *ExternalID = NULL;
6445: xmlChar *URI = NULL;
1.21 daniel 6446:
6447: /*
6448: * We know that '<!DOCTYPE' has been detected.
6449: */
1.40 daniel 6450: SKIP(9);
1.21 daniel 6451:
1.42 daniel 6452: SKIP_BLANKS;
1.21 daniel 6453:
6454: /*
6455: * Parse the DOCTYPE name.
6456: */
6457: name = xmlParseName(ctxt);
6458: if (name == NULL) {
1.55 daniel 6459: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 6460: ctxt->sax->error(ctxt->userData,
6461: "xmlParseDocTypeDecl : no DOCTYPE name !\n");
1.59 daniel 6462: ctxt->wellFormed = 0;
1.123 daniel 6463: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.21 daniel 6464: }
1.165 daniel 6465: ctxt->intSubName = name;
1.21 daniel 6466:
1.42 daniel 6467: SKIP_BLANKS;
1.21 daniel 6468:
6469: /*
1.22 daniel 6470: * Check for SystemID and ExternalID
6471: */
1.67 daniel 6472: URI = xmlParseExternalID(ctxt, &ExternalID, 1);
1.98 daniel 6473:
6474: if ((URI != NULL) || (ExternalID != NULL)) {
6475: ctxt->hasExternalSubset = 1;
6476: }
1.165 daniel 6477: ctxt->extSubURI = URI;
6478: ctxt->extSubSystem = ExternalID;
1.98 daniel 6479:
1.42 daniel 6480: SKIP_BLANKS;
1.36 daniel 6481:
1.76 daniel 6482: /*
1.165 daniel 6483: * Create and update the internal subset.
1.76 daniel 6484: */
1.72 daniel 6485: if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
1.74 daniel 6486: ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
1.22 daniel 6487:
6488: /*
1.140 daniel 6489: * Is there any internal subset declarations ?
6490: * they are handled separately in xmlParseInternalSubset()
6491: */
1.152 daniel 6492: if (RAW == '[')
1.140 daniel 6493: return;
6494:
6495: /*
6496: * We should be at the end of the DOCTYPE declaration.
6497: */
1.152 daniel 6498: if (RAW != '>') {
1.140 daniel 6499: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6500: ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
6501: ctxt->wellFormed = 0;
6502: ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
6503: }
6504: NEXT;
6505: }
6506:
6507: /**
6508: * xmlParseInternalsubset :
6509: * @ctxt: an XML parser context
6510: *
6511: * parse the internal subset declaration
6512: *
6513: * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
6514: */
6515:
6516: void
6517: xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
6518: /*
1.22 daniel 6519: * Is there any DTD definition ?
6520: */
1.152 daniel 6521: if (RAW == '[') {
1.96 daniel 6522: ctxt->instate = XML_PARSER_DTD;
1.40 daniel 6523: NEXT;
1.22 daniel 6524: /*
6525: * Parse the succession of Markup declarations and
6526: * PEReferences.
6527: * Subsequence (markupdecl | PEReference | S)*
6528: */
1.152 daniel 6529: while (RAW != ']') {
1.123 daniel 6530: const xmlChar *check = CUR_PTR;
1.115 daniel 6531: int cons = ctxt->input->consumed;
1.22 daniel 6532:
1.42 daniel 6533: SKIP_BLANKS;
1.22 daniel 6534: xmlParseMarkupDecl(ctxt);
1.50 daniel 6535: xmlParsePEReference(ctxt);
1.22 daniel 6536:
1.115 daniel 6537: /*
6538: * Pop-up of finished entities.
6539: */
1.152 daniel 6540: while ((RAW == 0) && (ctxt->inputNr > 1))
1.115 daniel 6541: xmlPopInput(ctxt);
6542:
1.118 daniel 6543: if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
1.55 daniel 6544: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6545: ctxt->sax->error(ctxt->userData,
1.140 daniel 6546: "xmlParseInternalSubset: error detected in Markup declaration\n");
1.59 daniel 6547: ctxt->wellFormed = 0;
1.123 daniel 6548: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.22 daniel 6549: break;
6550: }
6551: }
1.152 daniel 6552: if (RAW == ']') NEXT;
1.22 daniel 6553: }
6554:
6555: /*
6556: * We should be at the end of the DOCTYPE declaration.
1.21 daniel 6557: */
1.152 daniel 6558: if (RAW != '>') {
1.55 daniel 6559: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6560: ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
1.59 daniel 6561: ctxt->wellFormed = 0;
1.123 daniel 6562: ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
1.21 daniel 6563: }
1.40 daniel 6564: NEXT;
1.21 daniel 6565: }
6566:
1.50 daniel 6567: /**
6568: * xmlParseAttribute:
6569: * @ctxt: an XML parser context
1.123 daniel 6570: * @value: a xmlChar ** used to store the value of the attribute
1.50 daniel 6571: *
6572: * parse an attribute
1.3 veillard 6573: *
1.22 daniel 6574: * [41] Attribute ::= Name Eq AttValue
6575: *
1.98 daniel 6576: * [ WFC: No External Entity References ]
6577: * Attribute values cannot contain direct or indirect entity references
6578: * to external entities.
6579: *
6580: * [ WFC: No < in Attribute Values ]
6581: * The replacement text of any entity referred to directly or indirectly in
6582: * an attribute value (other than "<") must not contain a <.
6583: *
6584: * [ VC: Attribute Value Type ]
1.117 daniel 6585: * The attribute must have been declared; the value must be of the type
1.99 daniel 6586: * declared for it.
1.98 daniel 6587: *
1.22 daniel 6588: * [25] Eq ::= S? '=' S?
6589: *
1.29 daniel 6590: * With namespace:
6591: *
6592: * [NS 11] Attribute ::= QName Eq AttValue
1.43 daniel 6593: *
6594: * Also the case QName == xmlns:??? is handled independently as a namespace
6595: * definition.
1.69 daniel 6596: *
1.72 daniel 6597: * Returns the attribute name, and the value in *value.
1.3 veillard 6598: */
6599:
1.123 daniel 6600: xmlChar *
6601: xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
6602: xmlChar *name, *val;
1.3 veillard 6603:
1.72 daniel 6604: *value = NULL;
6605: name = xmlParseName(ctxt);
1.22 daniel 6606: if (name == NULL) {
1.55 daniel 6607: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6608: ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
1.59 daniel 6609: ctxt->wellFormed = 0;
1.123 daniel 6610: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.52 daniel 6611: return(NULL);
1.3 veillard 6612: }
6613:
6614: /*
1.29 daniel 6615: * read the value
1.3 veillard 6616: */
1.42 daniel 6617: SKIP_BLANKS;
1.152 daniel 6618: if (RAW == '=') {
1.40 daniel 6619: NEXT;
1.42 daniel 6620: SKIP_BLANKS;
1.72 daniel 6621: val = xmlParseAttValue(ctxt);
1.96 daniel 6622: ctxt->instate = XML_PARSER_CONTENT;
1.29 daniel 6623: } else {
1.55 daniel 6624: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6625: ctxt->sax->error(ctxt->userData,
1.59 daniel 6626: "Specification mandate value for attribute %s\n", name);
1.123 daniel 6627: ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
1.59 daniel 6628: ctxt->wellFormed = 0;
1.170 ! daniel 6629: xmlFree(name);
1.52 daniel 6630: return(NULL);
1.43 daniel 6631: }
6632:
1.72 daniel 6633: *value = val;
6634: return(name);
1.3 veillard 6635: }
6636:
1.50 daniel 6637: /**
6638: * xmlParseStartTag:
6639: * @ctxt: an XML parser context
6640: *
6641: * parse a start of tag either for rule element or
6642: * EmptyElement. In both case we don't parse the tag closing chars.
1.27 daniel 6643: *
6644: * [40] STag ::= '<' Name (S Attribute)* S? '>'
6645: *
1.98 daniel 6646: * [ WFC: Unique Att Spec ]
6647: * No attribute name may appear more than once in the same start-tag or
6648: * empty-element tag.
6649: *
1.29 daniel 6650: * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
6651: *
1.98 daniel 6652: * [ WFC: Unique Att Spec ]
6653: * No attribute name may appear more than once in the same start-tag or
6654: * empty-element tag.
6655: *
1.29 daniel 6656: * With namespace:
6657: *
6658: * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
6659: *
6660: * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
1.83 daniel 6661: *
1.129 daniel 6662: * Returne the element name parsed
1.2 veillard 6663: */
6664:
1.123 daniel 6665: xmlChar *
1.69 daniel 6666: xmlParseStartTag(xmlParserCtxtPtr ctxt) {
1.123 daniel 6667: xmlChar *name;
6668: xmlChar *attname;
6669: xmlChar *attvalue;
6670: const xmlChar **atts = NULL;
1.72 daniel 6671: int nbatts = 0;
6672: int maxatts = 0;
6673: int i;
1.2 veillard 6674:
1.152 daniel 6675: if (RAW != '<') return(NULL);
1.40 daniel 6676: NEXT;
1.3 veillard 6677:
1.72 daniel 6678: name = xmlParseName(ctxt);
1.59 daniel 6679: if (name == NULL) {
6680: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6681: ctxt->sax->error(ctxt->userData,
1.59 daniel 6682: "xmlParseStartTag: invalid element name\n");
1.123 daniel 6683: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 6684: ctxt->wellFormed = 0;
1.83 daniel 6685: return(NULL);
1.50 daniel 6686: }
6687:
6688: /*
1.3 veillard 6689: * Now parse the attributes, it ends up with the ending
6690: *
6691: * (S Attribute)* S?
6692: */
1.42 daniel 6693: SKIP_BLANKS;
1.91 daniel 6694: GROW;
1.168 daniel 6695:
1.153 daniel 6696: while ((IS_CHAR(RAW)) &&
1.152 daniel 6697: (RAW != '>') &&
6698: ((RAW != '/') || (NXT(1) != '>'))) {
1.123 daniel 6699: const xmlChar *q = CUR_PTR;
1.91 daniel 6700: int cons = ctxt->input->consumed;
1.29 daniel 6701:
1.72 daniel 6702: attname = xmlParseAttribute(ctxt, &attvalue);
6703: if ((attname != NULL) && (attvalue != NULL)) {
6704: /*
1.98 daniel 6705: * [ WFC: Unique Att Spec ]
6706: * No attribute name may appear more than once in the same
6707: * start-tag or empty-element tag.
1.72 daniel 6708: */
6709: for (i = 0; i < nbatts;i += 2) {
6710: if (!xmlStrcmp(atts[i], attname)) {
6711: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 6712: ctxt->sax->error(ctxt->userData,
6713: "Attribute %s redefined\n",
6714: attname);
1.72 daniel 6715: ctxt->wellFormed = 0;
1.123 daniel 6716: ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1.119 daniel 6717: xmlFree(attname);
6718: xmlFree(attvalue);
1.98 daniel 6719: goto failed;
1.72 daniel 6720: }
6721: }
6722:
6723: /*
6724: * Add the pair to atts
6725: */
6726: if (atts == NULL) {
6727: maxatts = 10;
1.123 daniel 6728: atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
1.72 daniel 6729: if (atts == NULL) {
1.86 daniel 6730: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 6731: maxatts * (long)sizeof(xmlChar *));
1.83 daniel 6732: return(NULL);
1.72 daniel 6733: }
1.127 daniel 6734: } else if (nbatts + 4 > maxatts) {
1.72 daniel 6735: maxatts *= 2;
1.123 daniel 6736: atts = (const xmlChar **) xmlRealloc(atts,
6737: maxatts * sizeof(xmlChar *));
1.72 daniel 6738: if (atts == NULL) {
1.86 daniel 6739: fprintf(stderr, "realloc of %ld byte failed\n",
1.123 daniel 6740: maxatts * (long)sizeof(xmlChar *));
1.83 daniel 6741: return(NULL);
1.72 daniel 6742: }
6743: }
6744: atts[nbatts++] = attname;
6745: atts[nbatts++] = attvalue;
6746: atts[nbatts] = NULL;
6747: atts[nbatts + 1] = NULL;
6748: }
6749:
1.116 daniel 6750: failed:
1.168 daniel 6751:
6752: if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
6753: break;
6754: if (!IS_BLANK(RAW)) {
6755: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6756: ctxt->sax->error(ctxt->userData,
6757: "attributes construct error\n");
6758: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
6759: ctxt->wellFormed = 0;
6760: }
1.42 daniel 6761: SKIP_BLANKS;
1.91 daniel 6762: if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
1.55 daniel 6763: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6764: ctxt->sax->error(ctxt->userData,
1.31 daniel 6765: "xmlParseStartTag: problem parsing attributes\n");
1.123 daniel 6766: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 6767: ctxt->wellFormed = 0;
1.29 daniel 6768: break;
1.3 veillard 6769: }
1.91 daniel 6770: GROW;
1.3 veillard 6771: }
6772:
1.43 daniel 6773: /*
1.72 daniel 6774: * SAX: Start of Element !
1.43 daniel 6775: */
1.72 daniel 6776: if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
1.74 daniel 6777: ctxt->sax->startElement(ctxt->userData, name, atts);
1.43 daniel 6778:
1.72 daniel 6779: if (atts != NULL) {
1.123 daniel 6780: for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
1.119 daniel 6781: xmlFree(atts);
1.72 daniel 6782: }
1.83 daniel 6783: return(name);
1.3 veillard 6784: }
6785:
1.50 daniel 6786: /**
6787: * xmlParseEndTag:
6788: * @ctxt: an XML parser context
6789: *
6790: * parse an end of tag
1.27 daniel 6791: *
6792: * [42] ETag ::= '</' Name S? '>'
1.29 daniel 6793: *
6794: * With namespace
6795: *
1.72 daniel 6796: * [NS 9] ETag ::= '</' QName S? '>'
1.7 veillard 6797: */
6798:
1.55 daniel 6799: void
1.140 daniel 6800: xmlParseEndTag(xmlParserCtxtPtr ctxt) {
1.123 daniel 6801: xmlChar *name;
1.140 daniel 6802: xmlChar *oldname;
1.7 veillard 6803:
1.91 daniel 6804: GROW;
1.152 daniel 6805: if ((RAW != '<') || (NXT(1) != '/')) {
1.55 daniel 6806: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6807: ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
1.59 daniel 6808: ctxt->wellFormed = 0;
1.123 daniel 6809: ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
1.27 daniel 6810: return;
6811: }
1.40 daniel 6812: SKIP(2);
1.7 veillard 6813:
1.72 daniel 6814: name = xmlParseName(ctxt);
1.7 veillard 6815:
6816: /*
6817: * We should definitely be at the ending "S? '>'" part
6818: */
1.91 daniel 6819: GROW;
1.42 daniel 6820: SKIP_BLANKS;
1.153 daniel 6821: if ((!IS_CHAR(RAW)) || (RAW != '>')) {
1.55 daniel 6822: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6823: ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
1.123 daniel 6824: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59 daniel 6825: ctxt->wellFormed = 0;
1.7 veillard 6826: } else
1.40 daniel 6827: NEXT;
1.7 veillard 6828:
1.72 daniel 6829: /*
1.98 daniel 6830: * [ WFC: Element Type Match ]
6831: * The Name in an element's end-tag must match the element type in the
6832: * start-tag.
6833: *
1.83 daniel 6834: */
1.147 daniel 6835: if ((name == NULL) || (ctxt->name == NULL) ||
6836: (xmlStrcmp(name, ctxt->name))) {
6837: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
6838: if ((name != NULL) && (ctxt->name != NULL)) {
6839: ctxt->sax->error(ctxt->userData,
6840: "Opening and ending tag mismatch: %s and %s\n",
6841: ctxt->name, name);
6842: } else if (ctxt->name != NULL) {
6843: ctxt->sax->error(ctxt->userData,
6844: "Ending tag eror for: %s\n", ctxt->name);
6845: } else {
6846: ctxt->sax->error(ctxt->userData,
6847: "Ending tag error: internal error ???\n");
6848: }
1.122 daniel 6849:
1.147 daniel 6850: }
1.123 daniel 6851: ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
1.83 daniel 6852: ctxt->wellFormed = 0;
6853: }
6854:
6855: /*
1.72 daniel 6856: * SAX: End of Tag
6857: */
6858: if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.74 daniel 6859: ctxt->sax->endElement(ctxt->userData, name);
1.72 daniel 6860:
6861: if (name != NULL)
1.119 daniel 6862: xmlFree(name);
1.140 daniel 6863: oldname = namePop(ctxt);
6864: if (oldname != NULL) {
6865: #ifdef DEBUG_STACK
6866: fprintf(stderr,"Close: popped %s\n", oldname);
6867: #endif
6868: xmlFree(oldname);
6869: }
1.7 veillard 6870: return;
6871: }
6872:
1.50 daniel 6873: /**
6874: * xmlParseCDSect:
6875: * @ctxt: an XML parser context
6876: *
6877: * Parse escaped pure raw content.
1.29 daniel 6878: *
6879: * [18] CDSect ::= CDStart CData CDEnd
6880: *
6881: * [19] CDStart ::= '<![CDATA['
6882: *
6883: * [20] Data ::= (Char* - (Char* ']]>' Char*))
6884: *
6885: * [21] CDEnd ::= ']]>'
1.3 veillard 6886: */
1.55 daniel 6887: void
6888: xmlParseCDSect(xmlParserCtxtPtr ctxt) {
1.135 daniel 6889: xmlChar *buf = NULL;
6890: int len = 0;
1.140 daniel 6891: int size = XML_PARSER_BUFFER_SIZE;
1.152 daniel 6892: int r, rl;
6893: int s, sl;
6894: int cur, l;
1.3 veillard 6895:
1.106 daniel 6896: if ((NXT(0) == '<') && (NXT(1) == '!') &&
1.40 daniel 6897: (NXT(2) == '[') && (NXT(3) == 'C') &&
6898: (NXT(4) == 'D') && (NXT(5) == 'A') &&
6899: (NXT(6) == 'T') && (NXT(7) == 'A') &&
6900: (NXT(8) == '[')) {
6901: SKIP(9);
1.29 daniel 6902: } else
1.45 daniel 6903: return;
1.109 daniel 6904:
6905: ctxt->instate = XML_PARSER_CDATA_SECTION;
1.152 daniel 6906: r = CUR_CHAR(rl);
6907: if (!IS_CHAR(r)) {
1.55 daniel 6908: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 6909: ctxt->sax->error(ctxt->userData,
1.135 daniel 6910: "CData section not finished\n");
1.59 daniel 6911: ctxt->wellFormed = 0;
1.123 daniel 6912: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.109 daniel 6913: ctxt->instate = XML_PARSER_CONTENT;
1.45 daniel 6914: return;
1.3 veillard 6915: }
1.152 daniel 6916: NEXTL(rl);
6917: s = CUR_CHAR(sl);
6918: if (!IS_CHAR(s)) {
1.55 daniel 6919: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 6920: ctxt->sax->error(ctxt->userData,
1.135 daniel 6921: "CData section not finished\n");
1.123 daniel 6922: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59 daniel 6923: ctxt->wellFormed = 0;
1.109 daniel 6924: ctxt->instate = XML_PARSER_CONTENT;
1.45 daniel 6925: return;
1.3 veillard 6926: }
1.152 daniel 6927: NEXTL(sl);
6928: cur = CUR_CHAR(l);
1.135 daniel 6929: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
6930: if (buf == NULL) {
6931: fprintf(stderr, "malloc of %d byte failed\n", size);
6932: return;
6933: }
1.108 veillard 6934: while (IS_CHAR(cur) &&
1.110 daniel 6935: ((r != ']') || (s != ']') || (cur != '>'))) {
1.152 daniel 6936: if (len + 5 >= size) {
1.135 daniel 6937: size *= 2;
6938: buf = xmlRealloc(buf, size * sizeof(xmlChar));
6939: if (buf == NULL) {
6940: fprintf(stderr, "realloc of %d byte failed\n", size);
6941: return;
6942: }
6943: }
1.152 daniel 6944: COPY_BUF(rl,buf,len,r);
1.110 daniel 6945: r = s;
1.152 daniel 6946: rl = sl;
1.110 daniel 6947: s = cur;
1.152 daniel 6948: sl = l;
6949: NEXTL(l);
6950: cur = CUR_CHAR(l);
1.3 veillard 6951: }
1.135 daniel 6952: buf[len] = 0;
1.109 daniel 6953: ctxt->instate = XML_PARSER_CONTENT;
1.152 daniel 6954: if (cur != '>') {
1.55 daniel 6955: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 6956: ctxt->sax->error(ctxt->userData,
1.135 daniel 6957: "CData section not finished\n%.50s\n", buf);
1.123 daniel 6958: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59 daniel 6959: ctxt->wellFormed = 0;
1.135 daniel 6960: xmlFree(buf);
1.45 daniel 6961: return;
1.3 veillard 6962: }
1.152 daniel 6963: NEXTL(l);
1.16 daniel 6964:
1.45 daniel 6965: /*
1.135 daniel 6966: * Ok the buffer is to be consumed as cdata.
1.45 daniel 6967: */
6968: if (ctxt->sax != NULL) {
1.107 daniel 6969: if (ctxt->sax->cdataBlock != NULL)
1.135 daniel 6970: ctxt->sax->cdataBlock(ctxt->userData, buf, len);
1.45 daniel 6971: }
1.135 daniel 6972: xmlFree(buf);
1.2 veillard 6973: }
6974:
1.50 daniel 6975: /**
6976: * xmlParseContent:
6977: * @ctxt: an XML parser context
6978: *
6979: * Parse a content:
1.2 veillard 6980: *
1.27 daniel 6981: * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
1.2 veillard 6982: */
6983:
1.55 daniel 6984: void
6985: xmlParseContent(xmlParserCtxtPtr ctxt) {
1.97 daniel 6986: GROW;
1.152 daniel 6987: while ((RAW != '<') || (NXT(1) != '/')) {
1.123 daniel 6988: const xmlChar *test = CUR_PTR;
1.91 daniel 6989: int cons = ctxt->input->consumed;
1.123 daniel 6990: xmlChar tok = ctxt->token;
1.27 daniel 6991:
6992: /*
1.152 daniel 6993: * Handle possible processed charrefs.
6994: */
6995: if (ctxt->token != 0) {
6996: xmlParseCharData(ctxt, 0);
6997: }
6998: /*
1.27 daniel 6999: * First case : a Processing Instruction.
7000: */
1.152 daniel 7001: else if ((RAW == '<') && (NXT(1) == '?')) {
1.27 daniel 7002: xmlParsePI(ctxt);
7003: }
1.72 daniel 7004:
1.27 daniel 7005: /*
7006: * Second case : a CDSection
7007: */
1.152 daniel 7008: else if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 7009: (NXT(2) == '[') && (NXT(3) == 'C') &&
7010: (NXT(4) == 'D') && (NXT(5) == 'A') &&
7011: (NXT(6) == 'T') && (NXT(7) == 'A') &&
7012: (NXT(8) == '[')) {
1.45 daniel 7013: xmlParseCDSect(ctxt);
1.27 daniel 7014: }
1.72 daniel 7015:
1.27 daniel 7016: /*
7017: * Third case : a comment
7018: */
1.152 daniel 7019: else if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 7020: (NXT(2) == '-') && (NXT(3) == '-')) {
1.114 daniel 7021: xmlParseComment(ctxt);
1.97 daniel 7022: ctxt->instate = XML_PARSER_CONTENT;
1.27 daniel 7023: }
1.72 daniel 7024:
1.27 daniel 7025: /*
7026: * Fourth case : a sub-element.
7027: */
1.152 daniel 7028: else if (RAW == '<') {
1.72 daniel 7029: xmlParseElement(ctxt);
1.45 daniel 7030: }
1.72 daniel 7031:
1.45 daniel 7032: /*
1.50 daniel 7033: * Fifth case : a reference. If if has not been resolved,
7034: * parsing returns it's Name, create the node
1.45 daniel 7035: */
1.97 daniel 7036:
1.152 daniel 7037: else if (RAW == '&') {
1.77 daniel 7038: xmlParseReference(ctxt);
1.27 daniel 7039: }
1.72 daniel 7040:
1.27 daniel 7041: /*
7042: * Last case, text. Note that References are handled directly.
7043: */
7044: else {
1.45 daniel 7045: xmlParseCharData(ctxt, 0);
1.3 veillard 7046: }
1.14 veillard 7047:
1.91 daniel 7048: GROW;
1.14 veillard 7049: /*
1.45 daniel 7050: * Pop-up of finished entities.
1.14 veillard 7051: */
1.152 daniel 7052: while ((RAW == 0) && (ctxt->inputNr > 1))
1.69 daniel 7053: xmlPopInput(ctxt);
1.135 daniel 7054: SHRINK;
1.45 daniel 7055:
1.113 daniel 7056: if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
7057: (tok == ctxt->token)) {
1.55 daniel 7058: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7059: ctxt->sax->error(ctxt->userData,
1.59 daniel 7060: "detected an error in element content\n");
1.123 daniel 7061: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 7062: ctxt->wellFormed = 0;
1.29 daniel 7063: break;
7064: }
1.3 veillard 7065: }
1.2 veillard 7066: }
7067:
1.50 daniel 7068: /**
7069: * xmlParseElement:
7070: * @ctxt: an XML parser context
7071: *
7072: * parse an XML element, this is highly recursive
1.26 daniel 7073: *
7074: * [39] element ::= EmptyElemTag | STag content ETag
7075: *
1.98 daniel 7076: * [ WFC: Element Type Match ]
7077: * The Name in an element's end-tag must match the element type in the
7078: * start-tag.
7079: *
7080: * [ VC: Element Valid ]
1.117 daniel 7081: * An element is valid if there is a declaration matching elementdecl
1.99 daniel 7082: * where the Name matches the element type and one of the following holds:
7083: * - The declaration matches EMPTY and the element has no content.
7084: * - The declaration matches children and the sequence of child elements
7085: * belongs to the language generated by the regular expression in the
7086: * content model, with optional white space (characters matching the
7087: * nonterminal S) between each pair of child elements.
7088: * - The declaration matches Mixed and the content consists of character
7089: * data and child elements whose types match names in the content model.
7090: * - The declaration matches ANY, and the types of any child elements have
7091: * been declared.
1.2 veillard 7092: */
1.26 daniel 7093:
1.72 daniel 7094: void
1.69 daniel 7095: xmlParseElement(xmlParserCtxtPtr ctxt) {
1.123 daniel 7096: const xmlChar *openTag = CUR_PTR;
7097: xmlChar *name;
1.140 daniel 7098: xmlChar *oldname;
1.32 daniel 7099: xmlParserNodeInfo node_info;
1.118 daniel 7100: xmlNodePtr ret;
1.2 veillard 7101:
1.32 daniel 7102: /* Capture start position */
1.118 daniel 7103: if (ctxt->record_info) {
7104: node_info.begin_pos = ctxt->input->consumed +
7105: (CUR_PTR - ctxt->input->base);
7106: node_info.begin_line = ctxt->input->line;
7107: }
1.32 daniel 7108:
1.83 daniel 7109: name = xmlParseStartTag(ctxt);
7110: if (name == NULL) {
7111: return;
7112: }
1.140 daniel 7113: namePush(ctxt, name);
1.118 daniel 7114: ret = ctxt->node;
1.2 veillard 7115:
7116: /*
1.99 daniel 7117: * [ VC: Root Element Type ]
7118: * The Name in the document type declaration must match the element
7119: * type of the root element.
7120: */
1.105 daniel 7121: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
1.157 daniel 7122: ctxt->node && (ctxt->node == ctxt->myDoc->children))
1.102 daniel 7123: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1.99 daniel 7124:
7125: /*
1.2 veillard 7126: * Check for an Empty Element.
7127: */
1.152 daniel 7128: if ((RAW == '/') && (NXT(1) == '>')) {
1.40 daniel 7129: SKIP(2);
1.72 daniel 7130: if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.83 daniel 7131: ctxt->sax->endElement(ctxt->userData, name);
1.140 daniel 7132: oldname = namePop(ctxt);
7133: if (oldname != NULL) {
7134: #ifdef DEBUG_STACK
7135: fprintf(stderr,"Close: popped %s\n", oldname);
7136: #endif
7137: xmlFree(oldname);
7138: }
1.72 daniel 7139: return;
1.2 veillard 7140: }
1.152 daniel 7141: if (RAW == '>') {
1.91 daniel 7142: NEXT;
7143: } else {
1.55 daniel 7144: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7145: ctxt->sax->error(ctxt->userData,
7146: "Couldn't find end of Start Tag\n%.30s\n",
1.57 daniel 7147: openTag);
1.59 daniel 7148: ctxt->wellFormed = 0;
1.123 daniel 7149: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.45 daniel 7150:
7151: /*
7152: * end of parsing of this node.
7153: */
7154: nodePop(ctxt);
1.140 daniel 7155: oldname = namePop(ctxt);
7156: if (oldname != NULL) {
7157: #ifdef DEBUG_STACK
7158: fprintf(stderr,"Close: popped %s\n", oldname);
7159: #endif
7160: xmlFree(oldname);
7161: }
1.118 daniel 7162:
7163: /*
7164: * Capture end position and add node
7165: */
7166: if ( ret != NULL && ctxt->record_info ) {
7167: node_info.end_pos = ctxt->input->consumed +
7168: (CUR_PTR - ctxt->input->base);
7169: node_info.end_line = ctxt->input->line;
7170: node_info.node = ret;
7171: xmlParserAddNodeInfo(ctxt, &node_info);
7172: }
1.72 daniel 7173: return;
1.2 veillard 7174: }
7175:
7176: /*
7177: * Parse the content of the element:
7178: */
1.45 daniel 7179: xmlParseContent(ctxt);
1.153 daniel 7180: if (!IS_CHAR(RAW)) {
1.55 daniel 7181: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7182: ctxt->sax->error(ctxt->userData,
1.57 daniel 7183: "Premature end of data in tag %.30s\n", openTag);
1.59 daniel 7184: ctxt->wellFormed = 0;
1.123 daniel 7185: ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
1.45 daniel 7186:
7187: /*
7188: * end of parsing of this node.
7189: */
7190: nodePop(ctxt);
1.140 daniel 7191: oldname = namePop(ctxt);
7192: if (oldname != NULL) {
7193: #ifdef DEBUG_STACK
7194: fprintf(stderr,"Close: popped %s\n", oldname);
7195: #endif
7196: xmlFree(oldname);
7197: }
1.72 daniel 7198: return;
1.2 veillard 7199: }
7200:
7201: /*
1.27 daniel 7202: * parse the end of tag: '</' should be here.
1.2 veillard 7203: */
1.140 daniel 7204: xmlParseEndTag(ctxt);
1.118 daniel 7205:
7206: /*
7207: * Capture end position and add node
7208: */
7209: if ( ret != NULL && ctxt->record_info ) {
7210: node_info.end_pos = ctxt->input->consumed +
7211: (CUR_PTR - ctxt->input->base);
7212: node_info.end_line = ctxt->input->line;
7213: node_info.node = ret;
7214: xmlParserAddNodeInfo(ctxt, &node_info);
7215: }
1.2 veillard 7216: }
7217:
1.50 daniel 7218: /**
7219: * xmlParseVersionNum:
7220: * @ctxt: an XML parser context
7221: *
7222: * parse the XML version value.
1.29 daniel 7223: *
7224: * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
1.68 daniel 7225: *
7226: * Returns the string giving the XML version number, or NULL
1.29 daniel 7227: */
1.123 daniel 7228: xmlChar *
1.55 daniel 7229: xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
1.135 daniel 7230: xmlChar *buf = NULL;
7231: int len = 0;
7232: int size = 10;
7233: xmlChar cur;
1.29 daniel 7234:
1.135 daniel 7235: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
7236: if (buf == NULL) {
7237: fprintf(stderr, "malloc of %d byte failed\n", size);
7238: return(NULL);
7239: }
7240: cur = CUR;
1.152 daniel 7241: while (((cur >= 'a') && (cur <= 'z')) ||
7242: ((cur >= 'A') && (cur <= 'Z')) ||
7243: ((cur >= '0') && (cur <= '9')) ||
7244: (cur == '_') || (cur == '.') ||
7245: (cur == ':') || (cur == '-')) {
1.135 daniel 7246: if (len + 1 >= size) {
7247: size *= 2;
7248: buf = xmlRealloc(buf, size * sizeof(xmlChar));
7249: if (buf == NULL) {
7250: fprintf(stderr, "realloc of %d byte failed\n", size);
7251: return(NULL);
7252: }
7253: }
7254: buf[len++] = cur;
7255: NEXT;
7256: cur=CUR;
7257: }
7258: buf[len] = 0;
7259: return(buf);
1.29 daniel 7260: }
7261:
1.50 daniel 7262: /**
7263: * xmlParseVersionInfo:
7264: * @ctxt: an XML parser context
7265: *
7266: * parse the XML version.
1.29 daniel 7267: *
7268: * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
7269: *
7270: * [25] Eq ::= S? '=' S?
1.50 daniel 7271: *
1.68 daniel 7272: * Returns the version string, e.g. "1.0"
1.29 daniel 7273: */
7274:
1.123 daniel 7275: xmlChar *
1.55 daniel 7276: xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
1.123 daniel 7277: xmlChar *version = NULL;
7278: const xmlChar *q;
1.29 daniel 7279:
1.152 daniel 7280: if ((RAW == 'v') && (NXT(1) == 'e') &&
1.40 daniel 7281: (NXT(2) == 'r') && (NXT(3) == 's') &&
7282: (NXT(4) == 'i') && (NXT(5) == 'o') &&
7283: (NXT(6) == 'n')) {
7284: SKIP(7);
1.42 daniel 7285: SKIP_BLANKS;
1.152 daniel 7286: if (RAW != '=') {
1.55 daniel 7287: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7288: ctxt->sax->error(ctxt->userData,
7289: "xmlParseVersionInfo : expected '='\n");
1.59 daniel 7290: ctxt->wellFormed = 0;
1.123 daniel 7291: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31 daniel 7292: return(NULL);
7293: }
1.40 daniel 7294: NEXT;
1.42 daniel 7295: SKIP_BLANKS;
1.152 daniel 7296: if (RAW == '"') {
1.40 daniel 7297: NEXT;
7298: q = CUR_PTR;
1.29 daniel 7299: version = xmlParseVersionNum(ctxt);
1.152 daniel 7300: if (RAW != '"') {
1.55 daniel 7301: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7302: ctxt->sax->error(ctxt->userData,
7303: "String not closed\n%.50s\n", q);
1.59 daniel 7304: ctxt->wellFormed = 0;
1.123 daniel 7305: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 7306: } else
1.40 daniel 7307: NEXT;
1.152 daniel 7308: } else if (RAW == '\''){
1.40 daniel 7309: NEXT;
7310: q = CUR_PTR;
1.29 daniel 7311: version = xmlParseVersionNum(ctxt);
1.152 daniel 7312: if (RAW != '\'') {
1.55 daniel 7313: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7314: ctxt->sax->error(ctxt->userData,
7315: "String not closed\n%.50s\n", q);
1.123 daniel 7316: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59 daniel 7317: ctxt->wellFormed = 0;
1.55 daniel 7318: } else
1.40 daniel 7319: NEXT;
1.31 daniel 7320: } else {
1.55 daniel 7321: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7322: ctxt->sax->error(ctxt->userData,
1.59 daniel 7323: "xmlParseVersionInfo : expected ' or \"\n");
1.122 daniel 7324: ctxt->wellFormed = 0;
1.123 daniel 7325: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29 daniel 7326: }
7327: }
7328: return(version);
7329: }
7330:
1.50 daniel 7331: /**
7332: * xmlParseEncName:
7333: * @ctxt: an XML parser context
7334: *
7335: * parse the XML encoding name
1.29 daniel 7336: *
7337: * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1.50 daniel 7338: *
1.68 daniel 7339: * Returns the encoding name value or NULL
1.29 daniel 7340: */
1.123 daniel 7341: xmlChar *
1.55 daniel 7342: xmlParseEncName(xmlParserCtxtPtr ctxt) {
1.135 daniel 7343: xmlChar *buf = NULL;
7344: int len = 0;
7345: int size = 10;
7346: xmlChar cur;
1.29 daniel 7347:
1.135 daniel 7348: cur = CUR;
7349: if (((cur >= 'a') && (cur <= 'z')) ||
7350: ((cur >= 'A') && (cur <= 'Z'))) {
7351: buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
7352: if (buf == NULL) {
7353: fprintf(stderr, "malloc of %d byte failed\n", size);
7354: return(NULL);
7355: }
7356:
7357: buf[len++] = cur;
1.40 daniel 7358: NEXT;
1.135 daniel 7359: cur = CUR;
1.152 daniel 7360: while (((cur >= 'a') && (cur <= 'z')) ||
7361: ((cur >= 'A') && (cur <= 'Z')) ||
7362: ((cur >= '0') && (cur <= '9')) ||
7363: (cur == '.') || (cur == '_') ||
7364: (cur == '-')) {
1.135 daniel 7365: if (len + 1 >= size) {
7366: size *= 2;
7367: buf = xmlRealloc(buf, size * sizeof(xmlChar));
7368: if (buf == NULL) {
7369: fprintf(stderr, "realloc of %d byte failed\n", size);
7370: return(NULL);
7371: }
7372: }
7373: buf[len++] = cur;
7374: NEXT;
7375: cur = CUR;
7376: if (cur == 0) {
7377: SHRINK;
7378: GROW;
7379: cur = CUR;
7380: }
7381: }
7382: buf[len] = 0;
1.29 daniel 7383: } else {
1.55 daniel 7384: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7385: ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
1.59 daniel 7386: ctxt->wellFormed = 0;
1.123 daniel 7387: ctxt->errNo = XML_ERR_ENCODING_NAME;
1.29 daniel 7388: }
1.135 daniel 7389: return(buf);
1.29 daniel 7390: }
7391:
1.50 daniel 7392: /**
7393: * xmlParseEncodingDecl:
7394: * @ctxt: an XML parser context
7395: *
7396: * parse the XML encoding declaration
1.29 daniel 7397: *
7398: * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'")
1.50 daniel 7399: *
7400: * TODO: this should setup the conversion filters.
7401: *
1.68 daniel 7402: * Returns the encoding value or NULL
1.29 daniel 7403: */
7404:
1.123 daniel 7405: xmlChar *
1.55 daniel 7406: xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 7407: xmlChar *encoding = NULL;
7408: const xmlChar *q;
1.29 daniel 7409:
1.42 daniel 7410: SKIP_BLANKS;
1.152 daniel 7411: if ((RAW == 'e') && (NXT(1) == 'n') &&
1.40 daniel 7412: (NXT(2) == 'c') && (NXT(3) == 'o') &&
7413: (NXT(4) == 'd') && (NXT(5) == 'i') &&
7414: (NXT(6) == 'n') && (NXT(7) == 'g')) {
7415: SKIP(8);
1.42 daniel 7416: SKIP_BLANKS;
1.152 daniel 7417: if (RAW != '=') {
1.55 daniel 7418: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7419: ctxt->sax->error(ctxt->userData,
7420: "xmlParseEncodingDecl : expected '='\n");
1.59 daniel 7421: ctxt->wellFormed = 0;
1.123 daniel 7422: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31 daniel 7423: return(NULL);
7424: }
1.40 daniel 7425: NEXT;
1.42 daniel 7426: SKIP_BLANKS;
1.152 daniel 7427: if (RAW == '"') {
1.40 daniel 7428: NEXT;
7429: q = CUR_PTR;
1.29 daniel 7430: encoding = xmlParseEncName(ctxt);
1.152 daniel 7431: if (RAW != '"') {
1.55 daniel 7432: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7433: ctxt->sax->error(ctxt->userData,
7434: "String not closed\n%.50s\n", q);
1.59 daniel 7435: ctxt->wellFormed = 0;
1.123 daniel 7436: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 7437: } else
1.40 daniel 7438: NEXT;
1.152 daniel 7439: } else if (RAW == '\''){
1.40 daniel 7440: NEXT;
7441: q = CUR_PTR;
1.29 daniel 7442: encoding = xmlParseEncName(ctxt);
1.152 daniel 7443: if (RAW != '\'') {
1.55 daniel 7444: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7445: ctxt->sax->error(ctxt->userData,
7446: "String not closed\n%.50s\n", q);
1.59 daniel 7447: ctxt->wellFormed = 0;
1.123 daniel 7448: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 7449: } else
1.40 daniel 7450: NEXT;
1.152 daniel 7451: } else if (RAW == '"'){
1.55 daniel 7452: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7453: ctxt->sax->error(ctxt->userData,
1.59 daniel 7454: "xmlParseEncodingDecl : expected ' or \"\n");
7455: ctxt->wellFormed = 0;
1.123 daniel 7456: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29 daniel 7457: }
7458: }
7459: return(encoding);
7460: }
7461:
1.50 daniel 7462: /**
7463: * xmlParseSDDecl:
7464: * @ctxt: an XML parser context
7465: *
7466: * parse the XML standalone declaration
1.29 daniel 7467: *
7468: * [32] SDDecl ::= S 'standalone' Eq
7469: * (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
1.99 daniel 7470: *
7471: * [ VC: Standalone Document Declaration ]
7472: * TODO The standalone document declaration must have the value "no"
7473: * if any external markup declarations contain declarations of:
7474: * - attributes with default values, if elements to which these
7475: * attributes apply appear in the document without specifications
7476: * of values for these attributes, or
7477: * - entities (other than amp, lt, gt, apos, quot), if references
7478: * to those entities appear in the document, or
7479: * - attributes with values subject to normalization, where the
7480: * attribute appears in the document with a value which will change
7481: * as a result of normalization, or
7482: * - element types with element content, if white space occurs directly
7483: * within any instance of those types.
1.68 daniel 7484: *
7485: * Returns 1 if standalone, 0 otherwise
1.29 daniel 7486: */
7487:
1.55 daniel 7488: int
7489: xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
1.29 daniel 7490: int standalone = -1;
7491:
1.42 daniel 7492: SKIP_BLANKS;
1.152 daniel 7493: if ((RAW == 's') && (NXT(1) == 't') &&
1.40 daniel 7494: (NXT(2) == 'a') && (NXT(3) == 'n') &&
7495: (NXT(4) == 'd') && (NXT(5) == 'a') &&
7496: (NXT(6) == 'l') && (NXT(7) == 'o') &&
7497: (NXT(8) == 'n') && (NXT(9) == 'e')) {
7498: SKIP(10);
1.81 daniel 7499: SKIP_BLANKS;
1.152 daniel 7500: if (RAW != '=') {
1.55 daniel 7501: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7502: ctxt->sax->error(ctxt->userData,
1.59 daniel 7503: "XML standalone declaration : expected '='\n");
1.123 daniel 7504: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.59 daniel 7505: ctxt->wellFormed = 0;
1.32 daniel 7506: return(standalone);
7507: }
1.40 daniel 7508: NEXT;
1.42 daniel 7509: SKIP_BLANKS;
1.152 daniel 7510: if (RAW == '\''){
1.40 daniel 7511: NEXT;
1.152 daniel 7512: if ((RAW == 'n') && (NXT(1) == 'o')) {
1.29 daniel 7513: standalone = 0;
1.40 daniel 7514: SKIP(2);
1.152 daniel 7515: } else if ((RAW == 'y') && (NXT(1) == 'e') &&
1.40 daniel 7516: (NXT(2) == 's')) {
1.29 daniel 7517: standalone = 1;
1.40 daniel 7518: SKIP(3);
1.29 daniel 7519: } else {
1.55 daniel 7520: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7521: ctxt->sax->error(ctxt->userData,
7522: "standalone accepts only 'yes' or 'no'\n");
1.123 daniel 7523: ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59 daniel 7524: ctxt->wellFormed = 0;
1.29 daniel 7525: }
1.152 daniel 7526: if (RAW != '\'') {
1.55 daniel 7527: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7528: ctxt->sax->error(ctxt->userData, "String not closed\n");
1.123 daniel 7529: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59 daniel 7530: ctxt->wellFormed = 0;
1.55 daniel 7531: } else
1.40 daniel 7532: NEXT;
1.152 daniel 7533: } else if (RAW == '"'){
1.40 daniel 7534: NEXT;
1.152 daniel 7535: if ((RAW == 'n') && (NXT(1) == 'o')) {
1.29 daniel 7536: standalone = 0;
1.40 daniel 7537: SKIP(2);
1.152 daniel 7538: } else if ((RAW == 'y') && (NXT(1) == 'e') &&
1.40 daniel 7539: (NXT(2) == 's')) {
1.29 daniel 7540: standalone = 1;
1.40 daniel 7541: SKIP(3);
1.29 daniel 7542: } else {
1.55 daniel 7543: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7544: ctxt->sax->error(ctxt->userData,
1.59 daniel 7545: "standalone accepts only 'yes' or 'no'\n");
1.123 daniel 7546: ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59 daniel 7547: ctxt->wellFormed = 0;
1.29 daniel 7548: }
1.152 daniel 7549: if (RAW != '"') {
1.55 daniel 7550: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7551: ctxt->sax->error(ctxt->userData, "String not closed\n");
1.59 daniel 7552: ctxt->wellFormed = 0;
1.123 daniel 7553: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 7554: } else
1.40 daniel 7555: NEXT;
1.37 daniel 7556: } else {
1.55 daniel 7557: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7558: ctxt->sax->error(ctxt->userData,
7559: "Standalone value not found\n");
1.59 daniel 7560: ctxt->wellFormed = 0;
1.123 daniel 7561: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.37 daniel 7562: }
1.29 daniel 7563: }
7564: return(standalone);
7565: }
7566:
1.50 daniel 7567: /**
7568: * xmlParseXMLDecl:
7569: * @ctxt: an XML parser context
7570: *
7571: * parse an XML declaration header
1.29 daniel 7572: *
7573: * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1.1 veillard 7574: */
7575:
1.55 daniel 7576: void
7577: xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 7578: xmlChar *version;
1.1 veillard 7579:
7580: /*
1.19 daniel 7581: * We know that '<?xml' is here.
1.1 veillard 7582: */
1.40 daniel 7583: SKIP(5);
1.1 veillard 7584:
1.153 daniel 7585: if (!IS_BLANK(RAW)) {
1.59 daniel 7586: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7587: ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
1.123 daniel 7588: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 7589: ctxt->wellFormed = 0;
7590: }
1.42 daniel 7591: SKIP_BLANKS;
1.1 veillard 7592:
7593: /*
1.29 daniel 7594: * We should have the VersionInfo here.
1.1 veillard 7595: */
1.29 daniel 7596: version = xmlParseVersionInfo(ctxt);
7597: if (version == NULL)
1.45 daniel 7598: version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.72 daniel 7599: ctxt->version = xmlStrdup(version);
1.119 daniel 7600: xmlFree(version);
1.29 daniel 7601:
7602: /*
7603: * We may have the encoding declaration
7604: */
1.153 daniel 7605: if (!IS_BLANK(RAW)) {
1.152 daniel 7606: if ((RAW == '?') && (NXT(1) == '>')) {
1.59 daniel 7607: SKIP(2);
7608: return;
7609: }
7610: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7611: ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.123 daniel 7612: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 7613: ctxt->wellFormed = 0;
7614: }
1.164 daniel 7615: ctxt->input->encoding = xmlParseEncodingDecl(ctxt);
1.1 veillard 7616:
7617: /*
1.29 daniel 7618: * We may have the standalone status.
1.1 veillard 7619: */
1.164 daniel 7620: if ((ctxt->input->encoding != NULL) && (!IS_BLANK(RAW))) {
1.152 daniel 7621: if ((RAW == '?') && (NXT(1) == '>')) {
1.59 daniel 7622: SKIP(2);
7623: return;
7624: }
7625: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7626: ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.59 daniel 7627: ctxt->wellFormed = 0;
1.123 daniel 7628: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 7629: }
7630: SKIP_BLANKS;
1.167 daniel 7631: ctxt->input->standalone = xmlParseSDDecl(ctxt);
1.1 veillard 7632:
1.42 daniel 7633: SKIP_BLANKS;
1.152 daniel 7634: if ((RAW == '?') && (NXT(1) == '>')) {
1.40 daniel 7635: SKIP(2);
1.152 daniel 7636: } else if (RAW == '>') {
1.31 daniel 7637: /* Deprecated old WD ... */
1.55 daniel 7638: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7639: ctxt->sax->error(ctxt->userData,
7640: "XML declaration must end-up with '?>'\n");
1.59 daniel 7641: ctxt->wellFormed = 0;
1.123 daniel 7642: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40 daniel 7643: NEXT;
1.29 daniel 7644: } else {
1.55 daniel 7645: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 7646: ctxt->sax->error(ctxt->userData,
7647: "parsing XML declaration: '?>' expected\n");
1.59 daniel 7648: ctxt->wellFormed = 0;
1.123 daniel 7649: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40 daniel 7650: MOVETO_ENDTAG(CUR_PTR);
7651: NEXT;
1.29 daniel 7652: }
1.1 veillard 7653: }
7654:
1.50 daniel 7655: /**
7656: * xmlParseMisc:
7657: * @ctxt: an XML parser context
7658: *
7659: * parse an XML Misc* optionnal field.
1.21 daniel 7660: *
1.22 daniel 7661: * [27] Misc ::= Comment | PI | S
1.1 veillard 7662: */
7663:
1.55 daniel 7664: void
7665: xmlParseMisc(xmlParserCtxtPtr ctxt) {
1.152 daniel 7666: while (((RAW == '<') && (NXT(1) == '?')) ||
7667: ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 7668: (NXT(2) == '-') && (NXT(3) == '-')) ||
7669: IS_BLANK(CUR)) {
1.152 daniel 7670: if ((RAW == '<') && (NXT(1) == '?')) {
1.16 daniel 7671: xmlParsePI(ctxt);
1.40 daniel 7672: } else if (IS_BLANK(CUR)) {
7673: NEXT;
1.1 veillard 7674: } else
1.114 daniel 7675: xmlParseComment(ctxt);
1.1 veillard 7676: }
7677: }
7678:
1.50 daniel 7679: /**
7680: * xmlParseDocument :
7681: * @ctxt: an XML parser context
7682: *
7683: * parse an XML document (and build a tree if using the standard SAX
7684: * interface).
1.21 daniel 7685: *
1.22 daniel 7686: * [1] document ::= prolog element Misc*
1.29 daniel 7687: *
7688: * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
1.50 daniel 7689: *
1.68 daniel 7690: * Returns 0, -1 in case of error. the parser context is augmented
1.50 daniel 7691: * as a result of the parsing.
1.1 veillard 7692: */
7693:
1.55 daniel 7694: int
7695: xmlParseDocument(xmlParserCtxtPtr ctxt) {
1.156 daniel 7696: xmlChar start[4];
7697: xmlCharEncoding enc;
7698:
1.45 daniel 7699: xmlDefaultSAXHandlerInit();
7700:
1.91 daniel 7701: GROW;
7702:
1.14 veillard 7703: /*
1.44 daniel 7704: * SAX: beginning of the document processing.
7705: */
1.72 daniel 7706: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
1.74 daniel 7707: ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
1.44 daniel 7708:
1.156 daniel 7709: /*
7710: * Get the 4 first bytes and decode the charset
7711: * if enc != XML_CHAR_ENCODING_NONE
7712: * plug some encoding conversion routines.
7713: */
7714: start[0] = RAW;
7715: start[1] = NXT(1);
7716: start[2] = NXT(2);
7717: start[3] = NXT(3);
7718: enc = xmlDetectCharEncoding(start, 4);
7719: if (enc != XML_CHAR_ENCODING_NONE) {
7720: xmlSwitchEncoding(ctxt, enc);
7721: }
7722:
1.1 veillard 7723:
1.168 daniel 7724: #if 0
1.1 veillard 7725: /*
7726: * Wipe out everything which is before the first '<'
7727: */
1.153 daniel 7728: if (IS_BLANK(RAW)) {
1.59 daniel 7729: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7730: ctxt->sax->error(ctxt->userData,
1.59 daniel 7731: "Extra spaces at the beginning of the document are not allowed\n");
1.123 daniel 7732: ctxt->errNo = XML_ERR_DOCUMENT_START;
1.59 daniel 7733: ctxt->wellFormed = 0;
7734: SKIP_BLANKS;
7735: }
1.168 daniel 7736: #endif
1.59 daniel 7737:
7738: if (CUR == 0) {
7739: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7740: ctxt->sax->error(ctxt->userData, "Document is empty\n");
1.123 daniel 7741: ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
1.59 daniel 7742: ctxt->wellFormed = 0;
7743: }
1.1 veillard 7744:
7745: /*
7746: * Check for the XMLDecl in the Prolog.
7747: */
1.91 daniel 7748: GROW;
1.152 daniel 7749: if ((RAW == '<') && (NXT(1) == '?') &&
1.40 daniel 7750: (NXT(2) == 'x') && (NXT(3) == 'm') &&
1.142 daniel 7751: (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
1.19 daniel 7752: xmlParseXMLDecl(ctxt);
1.167 daniel 7753: ctxt->standalone = ctxt->input->standalone;
1.42 daniel 7754: SKIP_BLANKS;
1.164 daniel 7755: if ((ctxt->encoding == NULL) && (ctxt->input->encoding != NULL))
7756: ctxt->encoding = xmlStrdup(ctxt->input->encoding);
7757:
1.151 daniel 7758: #if 0
1.152 daniel 7759: } else if ((RAW == '<') && (NXT(1) == '?') &&
1.40 daniel 7760: (NXT(2) == 'X') && (NXT(3) == 'M') &&
1.142 daniel 7761: (NXT(4) == 'L') && (IS_BLANK(NXT(5)))) {
1.19 daniel 7762: /*
7763: * The first drafts were using <?XML and the final W3C REC
7764: * now use <?xml ...
7765: */
1.16 daniel 7766: xmlParseXMLDecl(ctxt);
1.42 daniel 7767: SKIP_BLANKS;
1.151 daniel 7768: #endif
1.1 veillard 7769: } else {
1.72 daniel 7770: ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.1 veillard 7771: }
1.72 daniel 7772: if ((ctxt->sax) && (ctxt->sax->startDocument))
1.74 daniel 7773: ctxt->sax->startDocument(ctxt->userData);
1.1 veillard 7774:
7775: /*
7776: * The Misc part of the Prolog
7777: */
1.91 daniel 7778: GROW;
1.16 daniel 7779: xmlParseMisc(ctxt);
1.1 veillard 7780:
7781: /*
1.29 daniel 7782: * Then possibly doc type declaration(s) and more Misc
1.21 daniel 7783: * (doctypedecl Misc*)?
7784: */
1.91 daniel 7785: GROW;
1.152 daniel 7786: if ((RAW == '<') && (NXT(1) == '!') &&
1.40 daniel 7787: (NXT(2) == 'D') && (NXT(3) == 'O') &&
7788: (NXT(4) == 'C') && (NXT(5) == 'T') &&
7789: (NXT(6) == 'Y') && (NXT(7) == 'P') &&
7790: (NXT(8) == 'E')) {
1.165 daniel 7791:
1.166 daniel 7792: ctxt->inSubset = 1;
1.22 daniel 7793: xmlParseDocTypeDecl(ctxt);
1.152 daniel 7794: if (RAW == '[') {
1.140 daniel 7795: ctxt->instate = XML_PARSER_DTD;
7796: xmlParseInternalSubset(ctxt);
7797: }
1.165 daniel 7798:
7799: /*
7800: * Create and update the external subset.
7801: */
1.166 daniel 7802: ctxt->inSubset = 2;
1.165 daniel 7803: if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL))
7804: ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
7805: ctxt->extSubSystem, ctxt->extSubURI);
1.166 daniel 7806: ctxt->inSubset = 0;
1.165 daniel 7807:
7808:
1.96 daniel 7809: ctxt->instate = XML_PARSER_PROLOG;
1.22 daniel 7810: xmlParseMisc(ctxt);
1.21 daniel 7811: }
7812:
7813: /*
7814: * Time to start parsing the tree itself
1.1 veillard 7815: */
1.91 daniel 7816: GROW;
1.152 daniel 7817: if (RAW != '<') {
1.59 daniel 7818: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 7819: ctxt->sax->error(ctxt->userData,
1.151 daniel 7820: "Start tag expected, '<' not found\n");
1.140 daniel 7821: ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
1.59 daniel 7822: ctxt->wellFormed = 0;
1.140 daniel 7823: ctxt->instate = XML_PARSER_EOF;
7824: } else {
7825: ctxt->instate = XML_PARSER_CONTENT;
7826: xmlParseElement(ctxt);
7827: ctxt->instate = XML_PARSER_EPILOG;
7828:
7829:
7830: /*
7831: * The Misc part at the end
7832: */
7833: xmlParseMisc(ctxt);
7834:
1.152 daniel 7835: if (RAW != 0) {
1.140 daniel 7836: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7837: ctxt->sax->error(ctxt->userData,
7838: "Extra content at the end of the document\n");
7839: ctxt->wellFormed = 0;
7840: ctxt->errNo = XML_ERR_DOCUMENT_END;
7841: }
7842: ctxt->instate = XML_PARSER_EOF;
1.59 daniel 7843: }
7844:
1.44 daniel 7845: /*
7846: * SAX: end of the document processing.
7847: */
1.72 daniel 7848: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
1.74 daniel 7849: ctxt->sax->endDocument(ctxt->userData);
1.151 daniel 7850:
7851: /*
7852: * Grab the encoding if it was added on-the-fly
7853: */
7854: if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
7855: (ctxt->myDoc->encoding == NULL)) {
7856: ctxt->myDoc->encoding = ctxt->encoding;
7857: ctxt->encoding = NULL;
7858: }
1.59 daniel 7859: if (! ctxt->wellFormed) return(-1);
1.16 daniel 7860: return(0);
7861: }
7862:
1.98 daniel 7863: /************************************************************************
7864: * *
1.128 daniel 7865: * Progressive parsing interfaces *
7866: * *
7867: ************************************************************************/
7868:
7869: /**
7870: * xmlParseLookupSequence:
7871: * @ctxt: an XML parser context
7872: * @first: the first char to lookup
1.140 daniel 7873: * @next: the next char to lookup or zero
7874: * @third: the next char to lookup or zero
1.128 daniel 7875: *
1.140 daniel 7876: * Try to find if a sequence (first, next, third) or just (first next) or
7877: * (first) is available in the input stream.
7878: * This function has a side effect of (possibly) incrementing ctxt->checkIndex
7879: * to avoid rescanning sequences of bytes, it DOES change the state of the
7880: * parser, do not use liberally.
1.128 daniel 7881: *
1.140 daniel 7882: * Returns the index to the current parsing point if the full sequence
7883: * is available, -1 otherwise.
1.128 daniel 7884: */
7885: int
1.140 daniel 7886: xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
7887: xmlChar next, xmlChar third) {
7888: int base, len;
7889: xmlParserInputPtr in;
7890: const xmlChar *buf;
7891:
7892: in = ctxt->input;
7893: if (in == NULL) return(-1);
7894: base = in->cur - in->base;
7895: if (base < 0) return(-1);
7896: if (ctxt->checkIndex > base)
7897: base = ctxt->checkIndex;
7898: if (in->buf == NULL) {
7899: buf = in->base;
7900: len = in->length;
7901: } else {
7902: buf = in->buf->buffer->content;
7903: len = in->buf->buffer->use;
7904: }
7905: /* take into account the sequence length */
7906: if (third) len -= 2;
7907: else if (next) len --;
7908: for (;base < len;base++) {
7909: if (buf[base] == first) {
7910: if (third != 0) {
7911: if ((buf[base + 1] != next) ||
7912: (buf[base + 2] != third)) continue;
7913: } else if (next != 0) {
7914: if (buf[base + 1] != next) continue;
7915: }
7916: ctxt->checkIndex = 0;
7917: #ifdef DEBUG_PUSH
7918: if (next == 0)
7919: fprintf(stderr, "PP: lookup '%c' found at %d\n",
7920: first, base);
7921: else if (third == 0)
7922: fprintf(stderr, "PP: lookup '%c%c' found at %d\n",
7923: first, next, base);
7924: else
7925: fprintf(stderr, "PP: lookup '%c%c%c' found at %d\n",
7926: first, next, third, base);
7927: #endif
7928: return(base - (in->cur - in->base));
7929: }
7930: }
7931: ctxt->checkIndex = base;
7932: #ifdef DEBUG_PUSH
7933: if (next == 0)
7934: fprintf(stderr, "PP: lookup '%c' failed\n", first);
7935: else if (third == 0)
7936: fprintf(stderr, "PP: lookup '%c%c' failed\n", first, next);
7937: else
7938: fprintf(stderr, "PP: lookup '%c%c%c' failed\n", first, next, third);
7939: #endif
7940: return(-1);
1.128 daniel 7941: }
7942:
7943: /**
1.143 daniel 7944: * xmlParseTryOrFinish:
1.128 daniel 7945: * @ctxt: an XML parser context
1.143 daniel 7946: * @terminate: last chunk indicator
1.128 daniel 7947: *
7948: * Try to progress on parsing
7949: *
7950: * Returns zero if no parsing was possible
7951: */
7952: int
1.143 daniel 7953: xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
1.128 daniel 7954: int ret = 0;
1.140 daniel 7955: xmlParserInputPtr in;
7956: int avail;
7957: xmlChar cur, next;
7958:
7959: #ifdef DEBUG_PUSH
7960: switch (ctxt->instate) {
7961: case XML_PARSER_EOF:
7962: fprintf(stderr, "PP: try EOF\n"); break;
7963: case XML_PARSER_START:
7964: fprintf(stderr, "PP: try START\n"); break;
7965: case XML_PARSER_MISC:
7966: fprintf(stderr, "PP: try MISC\n");break;
7967: case XML_PARSER_COMMENT:
7968: fprintf(stderr, "PP: try COMMENT\n");break;
7969: case XML_PARSER_PROLOG:
7970: fprintf(stderr, "PP: try PROLOG\n");break;
7971: case XML_PARSER_START_TAG:
7972: fprintf(stderr, "PP: try START_TAG\n");break;
7973: case XML_PARSER_CONTENT:
7974: fprintf(stderr, "PP: try CONTENT\n");break;
7975: case XML_PARSER_CDATA_SECTION:
7976: fprintf(stderr, "PP: try CDATA_SECTION\n");break;
7977: case XML_PARSER_END_TAG:
7978: fprintf(stderr, "PP: try END_TAG\n");break;
7979: case XML_PARSER_ENTITY_DECL:
7980: fprintf(stderr, "PP: try ENTITY_DECL\n");break;
7981: case XML_PARSER_ENTITY_VALUE:
7982: fprintf(stderr, "PP: try ENTITY_VALUE\n");break;
7983: case XML_PARSER_ATTRIBUTE_VALUE:
7984: fprintf(stderr, "PP: try ATTRIBUTE_VALUE\n");break;
7985: case XML_PARSER_DTD:
7986: fprintf(stderr, "PP: try DTD\n");break;
7987: case XML_PARSER_EPILOG:
7988: fprintf(stderr, "PP: try EPILOG\n");break;
7989: case XML_PARSER_PI:
7990: fprintf(stderr, "PP: try PI\n");break;
7991: }
7992: #endif
1.128 daniel 7993:
7994: while (1) {
1.140 daniel 7995: /*
7996: * Pop-up of finished entities.
7997: */
1.152 daniel 7998: while ((RAW == 0) && (ctxt->inputNr > 1))
1.140 daniel 7999: xmlPopInput(ctxt);
8000:
8001: in = ctxt->input;
8002: if (in == NULL) break;
8003: if (in->buf == NULL)
8004: avail = in->length - (in->cur - in->base);
8005: else
8006: avail = in->buf->buffer->use - (in->cur - in->base);
8007: if (avail < 1)
8008: goto done;
1.128 daniel 8009: switch (ctxt->instate) {
8010: case XML_PARSER_EOF:
1.140 daniel 8011: /*
8012: * Document parsing is done !
8013: */
8014: goto done;
8015: case XML_PARSER_START:
8016: /*
8017: * Very first chars read from the document flow.
8018: */
8019: cur = in->cur[0];
8020: if (IS_BLANK(cur)) {
8021: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
8022: ctxt->sax->setDocumentLocator(ctxt->userData,
8023: &xmlDefaultSAXLocator);
8024: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8025: ctxt->sax->error(ctxt->userData,
8026: "Extra spaces at the beginning of the document are not allowed\n");
8027: ctxt->errNo = XML_ERR_DOCUMENT_START;
8028: ctxt->wellFormed = 0;
8029: SKIP_BLANKS;
8030: ret++;
8031: if (in->buf == NULL)
8032: avail = in->length - (in->cur - in->base);
8033: else
8034: avail = in->buf->buffer->use - (in->cur - in->base);
8035: }
8036: if (avail < 2)
8037: goto done;
8038:
8039: cur = in->cur[0];
8040: next = in->cur[1];
8041: if (cur == 0) {
8042: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
8043: ctxt->sax->setDocumentLocator(ctxt->userData,
8044: &xmlDefaultSAXLocator);
8045: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8046: ctxt->sax->error(ctxt->userData, "Document is empty\n");
8047: ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
8048: ctxt->wellFormed = 0;
8049: ctxt->instate = XML_PARSER_EOF;
8050: #ifdef DEBUG_PUSH
8051: fprintf(stderr, "PP: entering EOF\n");
8052: #endif
8053: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
8054: ctxt->sax->endDocument(ctxt->userData);
8055: goto done;
8056: }
8057: if ((cur == '<') && (next == '?')) {
8058: /* PI or XML decl */
8059: if (avail < 5) return(ret);
1.143 daniel 8060: if ((!terminate) &&
8061: (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
1.140 daniel 8062: return(ret);
8063: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
8064: ctxt->sax->setDocumentLocator(ctxt->userData,
8065: &xmlDefaultSAXLocator);
8066: if ((in->cur[2] == 'x') &&
8067: (in->cur[3] == 'm') &&
1.142 daniel 8068: (in->cur[4] == 'l') &&
8069: (IS_BLANK(in->cur[5]))) {
1.140 daniel 8070: ret += 5;
8071: #ifdef DEBUG_PUSH
8072: fprintf(stderr, "PP: Parsing XML Decl\n");
8073: #endif
8074: xmlParseXMLDecl(ctxt);
1.167 daniel 8075: ctxt->standalone = ctxt->input->standalone;
1.164 daniel 8076: if ((ctxt->encoding == NULL) &&
8077: (ctxt->input->encoding != NULL))
8078: ctxt->encoding = xmlStrdup(ctxt->input->encoding);
1.140 daniel 8079: if ((ctxt->sax) && (ctxt->sax->startDocument))
8080: ctxt->sax->startDocument(ctxt->userData);
8081: ctxt->instate = XML_PARSER_MISC;
8082: #ifdef DEBUG_PUSH
8083: fprintf(stderr, "PP: entering MISC\n");
8084: #endif
8085: } else {
8086: ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
8087: if ((ctxt->sax) && (ctxt->sax->startDocument))
8088: ctxt->sax->startDocument(ctxt->userData);
8089: ctxt->instate = XML_PARSER_MISC;
8090: #ifdef DEBUG_PUSH
8091: fprintf(stderr, "PP: entering MISC\n");
8092: #endif
8093: }
8094: } else {
8095: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
8096: ctxt->sax->setDocumentLocator(ctxt->userData,
8097: &xmlDefaultSAXLocator);
8098: ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
8099: if ((ctxt->sax) && (ctxt->sax->startDocument))
8100: ctxt->sax->startDocument(ctxt->userData);
8101: ctxt->instate = XML_PARSER_MISC;
8102: #ifdef DEBUG_PUSH
8103: fprintf(stderr, "PP: entering MISC\n");
8104: #endif
8105: }
8106: break;
8107: case XML_PARSER_MISC:
8108: SKIP_BLANKS;
8109: if (in->buf == NULL)
8110: avail = in->length - (in->cur - in->base);
8111: else
8112: avail = in->buf->buffer->use - (in->cur - in->base);
8113: if (avail < 2)
8114: goto done;
8115: cur = in->cur[0];
8116: next = in->cur[1];
8117: if ((cur == '<') && (next == '?')) {
1.143 daniel 8118: if ((!terminate) &&
8119: (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
1.140 daniel 8120: goto done;
8121: #ifdef DEBUG_PUSH
8122: fprintf(stderr, "PP: Parsing PI\n");
8123: #endif
8124: xmlParsePI(ctxt);
8125: } else if ((cur == '<') && (next == '!') &&
8126: (in->cur[2] == '-') && (in->cur[3] == '-')) {
1.143 daniel 8127: if ((!terminate) &&
8128: (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
1.140 daniel 8129: goto done;
8130: #ifdef DEBUG_PUSH
8131: fprintf(stderr, "PP: Parsing Comment\n");
8132: #endif
8133: xmlParseComment(ctxt);
8134: ctxt->instate = XML_PARSER_MISC;
8135: } else if ((cur == '<') && (next == '!') &&
8136: (in->cur[2] == 'D') && (in->cur[3] == 'O') &&
8137: (in->cur[4] == 'C') && (in->cur[5] == 'T') &&
8138: (in->cur[6] == 'Y') && (in->cur[7] == 'P') &&
8139: (in->cur[8] == 'E')) {
1.143 daniel 8140: if ((!terminate) &&
8141: (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
1.140 daniel 8142: goto done;
8143: #ifdef DEBUG_PUSH
8144: fprintf(stderr, "PP: Parsing internal subset\n");
8145: #endif
1.166 daniel 8146: ctxt->inSubset = 1;
1.140 daniel 8147: xmlParseDocTypeDecl(ctxt);
1.152 daniel 8148: if (RAW == '[') {
1.140 daniel 8149: ctxt->instate = XML_PARSER_DTD;
8150: #ifdef DEBUG_PUSH
8151: fprintf(stderr, "PP: entering DTD\n");
8152: #endif
8153: } else {
1.166 daniel 8154: /*
8155: * Create and update the external subset.
8156: */
8157: ctxt->inSubset = 2;
8158: if ((ctxt->sax != NULL) &&
8159: (ctxt->sax->externalSubset != NULL))
8160: ctxt->sax->externalSubset(ctxt->userData,
8161: ctxt->intSubName, ctxt->extSubSystem,
8162: ctxt->extSubURI);
8163: ctxt->inSubset = 0;
1.140 daniel 8164: ctxt->instate = XML_PARSER_PROLOG;
8165: #ifdef DEBUG_PUSH
8166: fprintf(stderr, "PP: entering PROLOG\n");
8167: #endif
8168: }
8169: } else if ((cur == '<') && (next == '!') &&
8170: (avail < 9)) {
8171: goto done;
8172: } else {
8173: ctxt->instate = XML_PARSER_START_TAG;
8174: #ifdef DEBUG_PUSH
8175: fprintf(stderr, "PP: entering START_TAG\n");
8176: #endif
8177: }
8178: break;
1.128 daniel 8179: case XML_PARSER_PROLOG:
1.140 daniel 8180: SKIP_BLANKS;
8181: if (in->buf == NULL)
8182: avail = in->length - (in->cur - in->base);
8183: else
8184: avail = in->buf->buffer->use - (in->cur - in->base);
8185: if (avail < 2)
8186: goto done;
8187: cur = in->cur[0];
8188: next = in->cur[1];
8189: if ((cur == '<') && (next == '?')) {
1.143 daniel 8190: if ((!terminate) &&
8191: (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
1.140 daniel 8192: goto done;
8193: #ifdef DEBUG_PUSH
8194: fprintf(stderr, "PP: Parsing PI\n");
8195: #endif
8196: xmlParsePI(ctxt);
8197: } else if ((cur == '<') && (next == '!') &&
8198: (in->cur[2] == '-') && (in->cur[3] == '-')) {
1.143 daniel 8199: if ((!terminate) &&
8200: (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
1.140 daniel 8201: goto done;
8202: #ifdef DEBUG_PUSH
8203: fprintf(stderr, "PP: Parsing Comment\n");
8204: #endif
8205: xmlParseComment(ctxt);
8206: ctxt->instate = XML_PARSER_PROLOG;
8207: } else if ((cur == '<') && (next == '!') &&
8208: (avail < 4)) {
8209: goto done;
8210: } else {
8211: ctxt->instate = XML_PARSER_START_TAG;
8212: #ifdef DEBUG_PUSH
8213: fprintf(stderr, "PP: entering START_TAG\n");
8214: #endif
8215: }
8216: break;
8217: case XML_PARSER_EPILOG:
8218: SKIP_BLANKS;
8219: if (in->buf == NULL)
8220: avail = in->length - (in->cur - in->base);
8221: else
8222: avail = in->buf->buffer->use - (in->cur - in->base);
8223: if (avail < 2)
8224: goto done;
8225: cur = in->cur[0];
8226: next = in->cur[1];
8227: if ((cur == '<') && (next == '?')) {
1.143 daniel 8228: if ((!terminate) &&
8229: (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
1.140 daniel 8230: goto done;
8231: #ifdef DEBUG_PUSH
8232: fprintf(stderr, "PP: Parsing PI\n");
8233: #endif
8234: xmlParsePI(ctxt);
8235: ctxt->instate = XML_PARSER_EPILOG;
8236: } else if ((cur == '<') && (next == '!') &&
8237: (in->cur[2] == '-') && (in->cur[3] == '-')) {
1.143 daniel 8238: if ((!terminate) &&
8239: (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
1.140 daniel 8240: goto done;
8241: #ifdef DEBUG_PUSH
8242: fprintf(stderr, "PP: Parsing Comment\n");
8243: #endif
8244: xmlParseComment(ctxt);
8245: ctxt->instate = XML_PARSER_EPILOG;
8246: } else if ((cur == '<') && (next == '!') &&
8247: (avail < 4)) {
8248: goto done;
8249: } else {
8250: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8251: ctxt->sax->error(ctxt->userData,
8252: "Extra content at the end of the document\n");
8253: ctxt->wellFormed = 0;
8254: ctxt->errNo = XML_ERR_DOCUMENT_END;
8255: ctxt->instate = XML_PARSER_EOF;
8256: #ifdef DEBUG_PUSH
8257: fprintf(stderr, "PP: entering EOF\n");
8258: #endif
8259: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
8260: ctxt->sax->endDocument(ctxt->userData);
8261: goto done;
8262: }
8263: break;
8264: case XML_PARSER_START_TAG: {
8265: xmlChar *name, *oldname;
8266:
8267: if (avail < 2)
8268: goto done;
8269: cur = in->cur[0];
8270: if (cur != '<') {
8271: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8272: ctxt->sax->error(ctxt->userData,
8273: "Start tag expect, '<' not found\n");
8274: ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
8275: ctxt->wellFormed = 0;
8276: ctxt->instate = XML_PARSER_EOF;
8277: #ifdef DEBUG_PUSH
8278: fprintf(stderr, "PP: entering EOF\n");
8279: #endif
8280: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
8281: ctxt->sax->endDocument(ctxt->userData);
8282: goto done;
8283: }
1.143 daniel 8284: if ((!terminate) &&
8285: (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
1.140 daniel 8286: goto done;
8287: name = xmlParseStartTag(ctxt);
8288: if (name == NULL) {
8289: ctxt->instate = XML_PARSER_EOF;
8290: #ifdef DEBUG_PUSH
8291: fprintf(stderr, "PP: entering EOF\n");
8292: #endif
8293: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
8294: ctxt->sax->endDocument(ctxt->userData);
8295: goto done;
8296: }
8297: namePush(ctxt, xmlStrdup(name));
8298:
8299: /*
8300: * [ VC: Root Element Type ]
8301: * The Name in the document type declaration must match
8302: * the element type of the root element.
8303: */
8304: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
1.157 daniel 8305: ctxt->node && (ctxt->node == ctxt->myDoc->children))
1.140 daniel 8306: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
8307:
8308: /*
8309: * Check for an Empty Element.
8310: */
1.152 daniel 8311: if ((RAW == '/') && (NXT(1) == '>')) {
1.140 daniel 8312: SKIP(2);
8313: if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
8314: ctxt->sax->endElement(ctxt->userData, name);
8315: xmlFree(name);
8316: oldname = namePop(ctxt);
8317: if (oldname != NULL) {
8318: #ifdef DEBUG_STACK
8319: fprintf(stderr,"Close: popped %s\n", oldname);
8320: #endif
8321: xmlFree(oldname);
8322: }
8323: if (ctxt->name == NULL) {
8324: ctxt->instate = XML_PARSER_EPILOG;
8325: #ifdef DEBUG_PUSH
8326: fprintf(stderr, "PP: entering EPILOG\n");
8327: #endif
8328: } else {
8329: ctxt->instate = XML_PARSER_CONTENT;
8330: #ifdef DEBUG_PUSH
8331: fprintf(stderr, "PP: entering CONTENT\n");
8332: #endif
8333: }
8334: break;
8335: }
1.152 daniel 8336: if (RAW == '>') {
1.140 daniel 8337: NEXT;
8338: } else {
8339: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8340: ctxt->sax->error(ctxt->userData,
8341: "Couldn't find end of Start Tag %s\n",
8342: name);
8343: ctxt->wellFormed = 0;
8344: ctxt->errNo = XML_ERR_GT_REQUIRED;
8345:
8346: /*
8347: * end of parsing of this node.
8348: */
8349: nodePop(ctxt);
8350: oldname = namePop(ctxt);
8351: if (oldname != NULL) {
8352: #ifdef DEBUG_STACK
8353: fprintf(stderr,"Close: popped %s\n", oldname);
8354: #endif
8355: xmlFree(oldname);
8356: }
8357: }
8358: xmlFree(name);
8359: ctxt->instate = XML_PARSER_CONTENT;
8360: #ifdef DEBUG_PUSH
8361: fprintf(stderr, "PP: entering CONTENT\n");
8362: #endif
8363: break;
8364: }
1.128 daniel 8365: case XML_PARSER_CONTENT:
1.140 daniel 8366: /*
8367: * Handle preparsed entities and charRef
8368: */
8369: if (ctxt->token != 0) {
8370: xmlChar cur[2] = { 0 , 0 } ;
8371:
8372: cur[0] = (xmlChar) ctxt->token;
8373: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
8374: ctxt->sax->characters(ctxt->userData, cur, 1);
8375: ctxt->token = 0;
8376: }
8377: if (avail < 2)
8378: goto done;
8379: cur = in->cur[0];
8380: next = in->cur[1];
8381: if ((cur == '<') && (next == '?')) {
1.143 daniel 8382: if ((!terminate) &&
8383: (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
1.140 daniel 8384: goto done;
8385: #ifdef DEBUG_PUSH
8386: fprintf(stderr, "PP: Parsing PI\n");
8387: #endif
8388: xmlParsePI(ctxt);
8389: } else if ((cur == '<') && (next == '!') &&
8390: (in->cur[2] == '-') && (in->cur[3] == '-')) {
1.143 daniel 8391: if ((!terminate) &&
8392: (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
1.140 daniel 8393: goto done;
8394: #ifdef DEBUG_PUSH
8395: fprintf(stderr, "PP: Parsing Comment\n");
8396: #endif
8397: xmlParseComment(ctxt);
8398: ctxt->instate = XML_PARSER_CONTENT;
8399: } else if ((cur == '<') && (in->cur[1] == '!') &&
8400: (in->cur[2] == '[') && (NXT(3) == 'C') &&
8401: (in->cur[4] == 'D') && (NXT(5) == 'A') &&
8402: (in->cur[6] == 'T') && (NXT(7) == 'A') &&
8403: (in->cur[8] == '[')) {
8404: SKIP(9);
8405: ctxt->instate = XML_PARSER_CDATA_SECTION;
8406: #ifdef DEBUG_PUSH
8407: fprintf(stderr, "PP: entering CDATA_SECTION\n");
8408: #endif
8409: break;
8410: } else if ((cur == '<') && (next == '!') &&
8411: (avail < 9)) {
8412: goto done;
8413: } else if ((cur == '<') && (next == '/')) {
8414: ctxt->instate = XML_PARSER_END_TAG;
8415: #ifdef DEBUG_PUSH
8416: fprintf(stderr, "PP: entering END_TAG\n");
8417: #endif
8418: break;
8419: } else if (cur == '<') {
8420: ctxt->instate = XML_PARSER_START_TAG;
8421: #ifdef DEBUG_PUSH
8422: fprintf(stderr, "PP: entering START_TAG\n");
8423: #endif
8424: break;
8425: } else if (cur == '&') {
1.143 daniel 8426: if ((!terminate) &&
8427: (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
1.140 daniel 8428: goto done;
8429: #ifdef DEBUG_PUSH
8430: fprintf(stderr, "PP: Parsing Reference\n");
8431: #endif
8432: /* TODO: check generation of subtrees if noent !!! */
8433: xmlParseReference(ctxt);
8434: } else {
1.156 daniel 8435: /* TODO Avoid the extra copy, handle directly !!! */
1.140 daniel 8436: /*
8437: * Goal of the following test is :
8438: * - minimize calls to the SAX 'character' callback
8439: * when they are mergeable
8440: * - handle an problem for isBlank when we only parse
8441: * a sequence of blank chars and the next one is
8442: * not available to check against '<' presence.
8443: * - tries to homogenize the differences in SAX
8444: * callbacks beween the push and pull versions
8445: * of the parser.
8446: */
8447: if ((ctxt->inputNr == 1) &&
8448: (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
1.143 daniel 8449: if ((!terminate) &&
8450: (xmlParseLookupSequence(ctxt, '<', 0, 0) < 0))
1.140 daniel 8451: goto done;
8452: }
8453: ctxt->checkIndex = 0;
8454: #ifdef DEBUG_PUSH
8455: fprintf(stderr, "PP: Parsing char data\n");
8456: #endif
8457: xmlParseCharData(ctxt, 0);
8458: }
8459: /*
8460: * Pop-up of finished entities.
8461: */
1.152 daniel 8462: while ((RAW == 0) && (ctxt->inputNr > 1))
1.140 daniel 8463: xmlPopInput(ctxt);
8464: break;
8465: case XML_PARSER_CDATA_SECTION: {
8466: /*
8467: * The Push mode need to have the SAX callback for
8468: * cdataBlock merge back contiguous callbacks.
8469: */
8470: int base;
8471:
8472: in = ctxt->input;
8473: base = xmlParseLookupSequence(ctxt, ']', ']', '>');
8474: if (base < 0) {
8475: if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
8476: if (ctxt->sax != NULL) {
8477: if (ctxt->sax->cdataBlock != NULL)
8478: ctxt->sax->cdataBlock(ctxt->userData, in->cur,
8479: XML_PARSER_BIG_BUFFER_SIZE);
8480: }
8481: SKIP(XML_PARSER_BIG_BUFFER_SIZE);
8482: ctxt->checkIndex = 0;
8483: }
8484: goto done;
8485: } else {
8486: if ((ctxt->sax != NULL) && (base > 0)) {
8487: if (ctxt->sax->cdataBlock != NULL)
8488: ctxt->sax->cdataBlock(ctxt->userData,
8489: in->cur, base);
8490: }
8491: SKIP(base + 3);
8492: ctxt->checkIndex = 0;
8493: ctxt->instate = XML_PARSER_CONTENT;
8494: #ifdef DEBUG_PUSH
8495: fprintf(stderr, "PP: entering CONTENT\n");
8496: #endif
8497: }
8498: break;
8499: }
1.141 daniel 8500: case XML_PARSER_END_TAG:
1.140 daniel 8501: if (avail < 2)
8502: goto done;
1.143 daniel 8503: if ((!terminate) &&
8504: (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
1.140 daniel 8505: goto done;
8506: xmlParseEndTag(ctxt);
8507: if (ctxt->name == NULL) {
8508: ctxt->instate = XML_PARSER_EPILOG;
8509: #ifdef DEBUG_PUSH
8510: fprintf(stderr, "PP: entering EPILOG\n");
8511: #endif
8512: } else {
8513: ctxt->instate = XML_PARSER_CONTENT;
8514: #ifdef DEBUG_PUSH
8515: fprintf(stderr, "PP: entering CONTENT\n");
8516: #endif
8517: }
8518: break;
8519: case XML_PARSER_DTD: {
8520: /*
8521: * Sorry but progressive parsing of the internal subset
8522: * is not expected to be supported. We first check that
8523: * the full content of the internal subset is available and
8524: * the parsing is launched only at that point.
8525: * Internal subset ends up with "']' S? '>'" in an unescaped
8526: * section and not in a ']]>' sequence which are conditional
8527: * sections (whoever argued to keep that crap in XML deserve
8528: * a place in hell !).
8529: */
8530: int base, i;
8531: xmlChar *buf;
8532: xmlChar quote = 0;
8533:
8534: base = in->cur - in->base;
8535: if (base < 0) return(0);
8536: if (ctxt->checkIndex > base)
8537: base = ctxt->checkIndex;
8538: buf = in->buf->buffer->content;
8539: for (;base < in->buf->buffer->use;base++) {
8540: if (quote != 0) {
8541: if (buf[base] == quote)
8542: quote = 0;
8543: continue;
8544: }
8545: if (buf[base] == '"') {
8546: quote = '"';
8547: continue;
8548: }
8549: if (buf[base] == '\'') {
8550: quote = '\'';
8551: continue;
8552: }
8553: if (buf[base] == ']') {
8554: if (base +1 >= in->buf->buffer->use)
8555: break;
8556: if (buf[base + 1] == ']') {
8557: /* conditional crap, skip both ']' ! */
8558: base++;
8559: continue;
8560: }
8561: for (i = 0;base + i < in->buf->buffer->use;i++) {
8562: if (buf[base + i] == '>')
8563: goto found_end_int_subset;
8564: }
8565: break;
8566: }
8567: }
8568: /*
8569: * We didn't found the end of the Internal subset
8570: */
8571: if (quote == 0)
8572: ctxt->checkIndex = base;
8573: #ifdef DEBUG_PUSH
8574: if (next == 0)
8575: fprintf(stderr, "PP: lookup of int subset end filed\n");
8576: #endif
8577: goto done;
8578:
8579: found_end_int_subset:
8580: xmlParseInternalSubset(ctxt);
1.166 daniel 8581: ctxt->inSubset = 2;
8582: if ((ctxt->sax != NULL) &&
8583: (ctxt->sax->externalSubset != NULL))
8584: ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
8585: ctxt->extSubSystem, ctxt->extSubURI);
8586: ctxt->inSubset = 0;
1.140 daniel 8587: ctxt->instate = XML_PARSER_PROLOG;
8588: ctxt->checkIndex = 0;
8589: #ifdef DEBUG_PUSH
8590: fprintf(stderr, "PP: entering PROLOG\n");
8591: #endif
8592: break;
8593: }
8594: case XML_PARSER_COMMENT:
8595: fprintf(stderr, "PP: internal error, state == COMMENT\n");
8596: ctxt->instate = XML_PARSER_CONTENT;
8597: #ifdef DEBUG_PUSH
8598: fprintf(stderr, "PP: entering CONTENT\n");
8599: #endif
8600: break;
8601: case XML_PARSER_PI:
8602: fprintf(stderr, "PP: internal error, state == PI\n");
8603: ctxt->instate = XML_PARSER_CONTENT;
8604: #ifdef DEBUG_PUSH
8605: fprintf(stderr, "PP: entering CONTENT\n");
8606: #endif
8607: break;
1.128 daniel 8608: case XML_PARSER_ENTITY_DECL:
1.140 daniel 8609: fprintf(stderr, "PP: internal error, state == ENTITY_DECL\n");
8610: ctxt->instate = XML_PARSER_DTD;
8611: #ifdef DEBUG_PUSH
8612: fprintf(stderr, "PP: entering DTD\n");
8613: #endif
8614: break;
1.128 daniel 8615: case XML_PARSER_ENTITY_VALUE:
1.140 daniel 8616: fprintf(stderr, "PP: internal error, state == ENTITY_VALUE\n");
8617: ctxt->instate = XML_PARSER_CONTENT;
8618: #ifdef DEBUG_PUSH
8619: fprintf(stderr, "PP: entering DTD\n");
8620: #endif
8621: break;
1.128 daniel 8622: case XML_PARSER_ATTRIBUTE_VALUE:
1.140 daniel 8623: fprintf(stderr, "PP: internal error, state == ATTRIBUTE_VALUE\n");
1.168 daniel 8624: ctxt->instate = XML_PARSER_START_TAG;
8625: #ifdef DEBUG_PUSH
8626: fprintf(stderr, "PP: entering START_TAG\n");
8627: #endif
8628: break;
8629: case XML_PARSER_SYSTEM_LITERAL:
8630: fprintf(stderr, "PP: internal error, state == SYSTEM_LITERAL\n");
1.140 daniel 8631: ctxt->instate = XML_PARSER_START_TAG;
8632: #ifdef DEBUG_PUSH
8633: fprintf(stderr, "PP: entering START_TAG\n");
8634: #endif
8635: break;
1.128 daniel 8636: }
8637: }
1.140 daniel 8638: done:
8639: #ifdef DEBUG_PUSH
8640: fprintf(stderr, "PP: done %d\n", ret);
8641: #endif
1.128 daniel 8642: return(ret);
8643: }
8644:
8645: /**
1.143 daniel 8646: * xmlParseTry:
8647: * @ctxt: an XML parser context
8648: *
8649: * Try to progress on parsing
8650: *
8651: * Returns zero if no parsing was possible
8652: */
8653: int
8654: xmlParseTry(xmlParserCtxtPtr ctxt) {
8655: return(xmlParseTryOrFinish(ctxt, 0));
8656: }
8657:
8658: /**
1.128 daniel 8659: * xmlParseChunk:
8660: * @ctxt: an XML parser context
8661: * @chunk: an char array
8662: * @size: the size in byte of the chunk
8663: * @terminate: last chunk indicator
8664: *
8665: * Parse a Chunk of memory
8666: *
8667: * Returns zero if no error, the xmlParserErrors otherwise.
8668: */
1.140 daniel 8669: int
1.128 daniel 8670: xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
8671: int terminate) {
1.132 daniel 8672: if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
1.140 daniel 8673: (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) {
8674: int base = ctxt->input->base - ctxt->input->buf->buffer->content;
8675: int cur = ctxt->input->cur - ctxt->input->base;
8676:
1.132 daniel 8677: xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
1.140 daniel 8678: ctxt->input->base = ctxt->input->buf->buffer->content + base;
8679: ctxt->input->cur = ctxt->input->base + cur;
8680: #ifdef DEBUG_PUSH
8681: fprintf(stderr, "PP: pushed %d\n", size);
8682: #endif
8683:
1.150 daniel 8684: if ((terminate) || (ctxt->input->buf->buffer->use > 80))
8685: xmlParseTryOrFinish(ctxt, terminate);
1.140 daniel 8686: } else if (ctxt->instate != XML_PARSER_EOF)
1.143 daniel 8687: xmlParseTryOrFinish(ctxt, terminate);
1.140 daniel 8688: if (terminate) {
1.151 daniel 8689: /*
8690: * Grab the encoding if it was added on-the-fly
8691: */
8692: if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
8693: (ctxt->myDoc->encoding == NULL)) {
8694: ctxt->myDoc->encoding = ctxt->encoding;
8695: ctxt->encoding = NULL;
8696: }
8697:
8698: /*
8699: * Check for termination
8700: */
1.140 daniel 8701: if ((ctxt->instate != XML_PARSER_EOF) &&
8702: (ctxt->instate != XML_PARSER_EPILOG)) {
8703: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8704: ctxt->sax->error(ctxt->userData,
8705: "Extra content at the end of the document\n");
8706: ctxt->wellFormed = 0;
8707: ctxt->errNo = XML_ERR_DOCUMENT_END;
8708: }
8709: if (ctxt->instate != XML_PARSER_EOF) {
8710: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
8711: ctxt->sax->endDocument(ctxt->userData);
8712: }
8713: ctxt->instate = XML_PARSER_EOF;
1.128 daniel 8714: }
8715: return((xmlParserErrors) ctxt->errNo);
8716: }
8717:
8718: /************************************************************************
8719: * *
1.98 daniel 8720: * I/O front end functions to the parser *
8721: * *
8722: ************************************************************************/
8723:
1.50 daniel 8724: /**
1.140 daniel 8725: * xmlCreatePushParserCtxt :
8726: * @sax: a SAX handler
8727: * @user_data: The user data returned on SAX callbacks
8728: * @chunk: a pointer to an array of chars
8729: * @size: number of chars in the array
8730: * @filename: an optional file name or URI
8731: *
8732: * Create a parser context for using the XML parser in push mode
8733: * To allow content encoding detection, @size should be >= 4
8734: * The value of @filename is used for fetching external entities
8735: * and error/warning reports.
8736: *
8737: * Returns the new parser context or NULL
8738: */
8739: xmlParserCtxtPtr
8740: xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
8741: const char *chunk, int size, const char *filename) {
8742: xmlParserCtxtPtr ctxt;
8743: xmlParserInputPtr inputStream;
8744: xmlParserInputBufferPtr buf;
8745: xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
8746:
8747: /*
1.156 daniel 8748: * plug some encoding conversion routines
1.140 daniel 8749: */
8750: if ((chunk != NULL) && (size >= 4))
1.156 daniel 8751: enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
1.140 daniel 8752:
8753: buf = xmlAllocParserInputBuffer(enc);
8754: if (buf == NULL) return(NULL);
8755:
8756: ctxt = xmlNewParserCtxt();
8757: if (ctxt == NULL) {
8758: xmlFree(buf);
8759: return(NULL);
8760: }
8761: if (sax != NULL) {
8762: if (ctxt->sax != &xmlDefaultSAXHandler)
8763: xmlFree(ctxt->sax);
8764: ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
8765: if (ctxt->sax == NULL) {
8766: xmlFree(buf);
8767: xmlFree(ctxt);
8768: return(NULL);
8769: }
8770: memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
8771: if (user_data != NULL)
8772: ctxt->userData = user_data;
8773: }
8774: if (filename == NULL) {
8775: ctxt->directory = NULL;
8776: } else {
8777: ctxt->directory = xmlParserGetDirectory(filename);
8778: }
8779:
8780: inputStream = xmlNewInputStream(ctxt);
8781: if (inputStream == NULL) {
8782: xmlFreeParserCtxt(ctxt);
8783: return(NULL);
8784: }
8785:
8786: if (filename == NULL)
8787: inputStream->filename = NULL;
8788: else
8789: inputStream->filename = xmlMemStrdup(filename);
8790: inputStream->buf = buf;
8791: inputStream->base = inputStream->buf->buffer->content;
8792: inputStream->cur = inputStream->buf->buffer->content;
1.156 daniel 8793: if (enc != XML_CHAR_ENCODING_NONE) {
8794: xmlSwitchEncoding(ctxt, enc);
8795: }
1.140 daniel 8796:
8797: inputPush(ctxt, inputStream);
8798:
8799: if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
8800: (ctxt->input->buf != NULL)) {
8801: xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
8802: #ifdef DEBUG_PUSH
8803: fprintf(stderr, "PP: pushed %d\n", size);
8804: #endif
8805: }
8806:
8807: return(ctxt);
8808: }
8809:
8810: /**
1.86 daniel 8811: * xmlCreateDocParserCtxt :
1.123 daniel 8812: * @cur: a pointer to an array of xmlChar
1.50 daniel 8813: *
1.69 daniel 8814: * Create a parser context for an XML in-memory document.
8815: *
8816: * Returns the new parser context or NULL
1.16 daniel 8817: */
1.69 daniel 8818: xmlParserCtxtPtr
1.123 daniel 8819: xmlCreateDocParserCtxt(xmlChar *cur) {
1.16 daniel 8820: xmlParserCtxtPtr ctxt;
1.40 daniel 8821: xmlParserInputPtr input;
1.16 daniel 8822:
1.97 daniel 8823: ctxt = xmlNewParserCtxt();
1.16 daniel 8824: if (ctxt == NULL) {
8825: return(NULL);
8826: }
1.96 daniel 8827: input = xmlNewInputStream(ctxt);
1.40 daniel 8828: if (input == NULL) {
1.97 daniel 8829: xmlFreeParserCtxt(ctxt);
1.40 daniel 8830: return(NULL);
8831: }
8832:
8833: input->base = cur;
8834: input->cur = cur;
8835:
8836: inputPush(ctxt, input);
1.69 daniel 8837: return(ctxt);
8838: }
8839:
8840: /**
8841: * xmlSAXParseDoc :
8842: * @sax: the SAX handler block
1.123 daniel 8843: * @cur: a pointer to an array of xmlChar
1.69 daniel 8844: * @recovery: work in recovery mode, i.e. tries to read no Well Formed
8845: * documents
8846: *
8847: * parse an XML in-memory document and build a tree.
8848: * It use the given SAX function block to handle the parsing callback.
8849: * If sax is NULL, fallback to the default DOM tree building routines.
8850: *
8851: * Returns the resulting document tree
8852: */
8853:
8854: xmlDocPtr
1.123 daniel 8855: xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
1.69 daniel 8856: xmlDocPtr ret;
8857: xmlParserCtxtPtr ctxt;
8858:
8859: if (cur == NULL) return(NULL);
1.16 daniel 8860:
8861:
1.69 daniel 8862: ctxt = xmlCreateDocParserCtxt(cur);
8863: if (ctxt == NULL) return(NULL);
1.74 daniel 8864: if (sax != NULL) {
8865: ctxt->sax = sax;
8866: ctxt->userData = NULL;
8867: }
1.69 daniel 8868:
1.16 daniel 8869: xmlParseDocument(ctxt);
1.72 daniel 8870: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 8871: else {
8872: ret = NULL;
1.72 daniel 8873: xmlFreeDoc(ctxt->myDoc);
8874: ctxt->myDoc = NULL;
1.59 daniel 8875: }
1.86 daniel 8876: if (sax != NULL)
8877: ctxt->sax = NULL;
1.69 daniel 8878: xmlFreeParserCtxt(ctxt);
1.16 daniel 8879:
1.1 veillard 8880: return(ret);
8881: }
8882:
1.50 daniel 8883: /**
1.55 daniel 8884: * xmlParseDoc :
1.123 daniel 8885: * @cur: a pointer to an array of xmlChar
1.55 daniel 8886: *
8887: * parse an XML in-memory document and build a tree.
8888: *
1.68 daniel 8889: * Returns the resulting document tree
1.55 daniel 8890: */
8891:
1.69 daniel 8892: xmlDocPtr
1.123 daniel 8893: xmlParseDoc(xmlChar *cur) {
1.59 daniel 8894: return(xmlSAXParseDoc(NULL, cur, 0));
1.76 daniel 8895: }
8896:
8897: /**
8898: * xmlSAXParseDTD :
8899: * @sax: the SAX handler block
8900: * @ExternalID: a NAME* containing the External ID of the DTD
8901: * @SystemID: a NAME* containing the URL to the DTD
8902: *
8903: * Load and parse an external subset.
8904: *
8905: * Returns the resulting xmlDtdPtr or NULL in case of error.
8906: */
8907:
8908: xmlDtdPtr
1.123 daniel 8909: xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
8910: const xmlChar *SystemID) {
1.76 daniel 8911: xmlDtdPtr ret = NULL;
8912: xmlParserCtxtPtr ctxt;
1.83 daniel 8913: xmlParserInputPtr input = NULL;
1.76 daniel 8914: xmlCharEncoding enc;
8915:
8916: if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
8917:
1.97 daniel 8918: ctxt = xmlNewParserCtxt();
1.76 daniel 8919: if (ctxt == NULL) {
8920: return(NULL);
8921: }
8922:
8923: /*
8924: * Set-up the SAX context
8925: */
8926: if (ctxt == NULL) return(NULL);
8927: if (sax != NULL) {
1.93 veillard 8928: if (ctxt->sax != NULL)
1.119 daniel 8929: xmlFree(ctxt->sax);
1.76 daniel 8930: ctxt->sax = sax;
8931: ctxt->userData = NULL;
8932: }
8933:
8934: /*
8935: * Ask the Entity resolver to load the damn thing
8936: */
8937:
8938: if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
8939: input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
8940: if (input == NULL) {
1.86 daniel 8941: if (sax != NULL) ctxt->sax = NULL;
1.76 daniel 8942: xmlFreeParserCtxt(ctxt);
8943: return(NULL);
8944: }
8945:
8946: /*
1.156 daniel 8947: * plug some encoding conversion routines here.
1.76 daniel 8948: */
8949: xmlPushInput(ctxt, input);
1.156 daniel 8950: enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
1.76 daniel 8951: xmlSwitchEncoding(ctxt, enc);
8952:
1.95 veillard 8953: if (input->filename == NULL)
1.156 daniel 8954: input->filename = (char *) xmlStrdup(SystemID);
1.76 daniel 8955: input->line = 1;
8956: input->col = 1;
8957: input->base = ctxt->input->cur;
8958: input->cur = ctxt->input->cur;
8959: input->free = NULL;
8960:
8961: /*
8962: * let's parse that entity knowing it's an external subset.
8963: */
1.79 daniel 8964: xmlParseExternalSubset(ctxt, ExternalID, SystemID);
1.76 daniel 8965:
8966: if (ctxt->myDoc != NULL) {
8967: if (ctxt->wellFormed) {
8968: ret = ctxt->myDoc->intSubset;
8969: ctxt->myDoc->intSubset = NULL;
8970: } else {
8971: ret = NULL;
8972: }
8973: xmlFreeDoc(ctxt->myDoc);
8974: ctxt->myDoc = NULL;
8975: }
1.86 daniel 8976: if (sax != NULL) ctxt->sax = NULL;
1.76 daniel 8977: xmlFreeParserCtxt(ctxt);
8978:
8979: return(ret);
8980: }
8981:
8982: /**
8983: * xmlParseDTD :
8984: * @ExternalID: a NAME* containing the External ID of the DTD
8985: * @SystemID: a NAME* containing the URL to the DTD
8986: *
8987: * Load and parse an external subset.
8988: *
8989: * Returns the resulting xmlDtdPtr or NULL in case of error.
8990: */
8991:
8992: xmlDtdPtr
1.123 daniel 8993: xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
1.76 daniel 8994: return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
1.59 daniel 8995: }
8996:
8997: /**
1.144 daniel 8998: * xmlSAXParseBalancedChunk :
8999: * @ctx: an XML parser context (possibly NULL)
9000: * @sax: the SAX handler bloc (possibly NULL)
9001: * @user_data: The user data returned on SAX callbacks (possibly NULL)
9002: * @input: a parser input stream
9003: * @enc: the encoding
9004: *
9005: * Parse a well-balanced chunk of an XML document
9006: * The user has to provide SAX callback block whose routines will be
9007: * called by the parser
9008: * The allowed sequence for the Well Balanced Chunk is the one defined by
9009: * the content production in the XML grammar:
9010: *
9011: * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
9012: *
9013: * Returns 0 id the chunk is well balanced, -1 in case of args problem and
9014: * the error code otherwise
9015: */
9016:
9017: int
9018: xmlSAXParseBalancedChunk(xmlParserCtxtPtr ctx, xmlSAXHandlerPtr sax,
9019: void *user_data, xmlParserInputPtr input,
9020: xmlCharEncoding enc) {
9021: xmlParserCtxtPtr ctxt;
9022: int ret;
9023:
9024: if (input == NULL) return(-1);
9025:
9026: if (ctx != NULL)
9027: ctxt = ctx;
9028: else {
9029: ctxt = xmlNewParserCtxt();
9030: if (ctxt == NULL)
9031: return(-1);
9032: if (sax == NULL)
9033: ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
9034: }
9035:
9036: /*
9037: * Set-up the SAX context
9038: */
9039: if (sax != NULL) {
9040: if (ctxt->sax != NULL)
9041: xmlFree(ctxt->sax);
9042: ctxt->sax = sax;
9043: ctxt->userData = user_data;
9044: }
9045:
9046: /*
9047: * plug some encoding conversion routines here.
9048: */
9049: xmlPushInput(ctxt, input);
9050: if (enc != XML_CHAR_ENCODING_NONE)
9051: xmlSwitchEncoding(ctxt, enc);
9052:
9053: /*
9054: * let's parse that entity knowing it's an external subset.
9055: */
9056: xmlParseContent(ctxt);
9057: ret = ctxt->errNo;
9058:
9059: if (ctx == NULL) {
9060: if (sax != NULL)
9061: ctxt->sax = NULL;
9062: else
9063: xmlFreeDoc(ctxt->myDoc);
9064: xmlFreeParserCtxt(ctxt);
9065: }
9066: return(ret);
9067: }
9068:
9069: /**
9070: * xmlParseBalancedChunk :
9071: * @doc: the document the chunk pertains to
9072: * @node: the node defining the context in which informations will be added
9073: *
9074: * Parse a well-balanced chunk of an XML document present in memory
9075: *
9076: * Returns the resulting list of nodes resulting from the parsing,
9077: * they are not added to @node
9078: */
9079:
9080: xmlNodePtr
9081: xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlNodePtr node) {
1.156 daniel 9082: /* TODO !!! */
9083: return(NULL);
1.144 daniel 9084: }
9085:
9086: /**
9087: * xmlParseBalancedChunkFile :
9088: * @doc: the document the chunk pertains to
9089: *
9090: * Parse a well-balanced chunk of an XML document contained in a file
9091: *
9092: * Returns the resulting list of nodes resulting from the parsing,
9093: * they are not added to @node
9094: */
9095:
9096: xmlNodePtr
9097: xmlParseBalancedChunkFile(xmlDocPtr doc, xmlNodePtr node) {
1.156 daniel 9098: /* TODO !!! */
9099: return(NULL);
1.144 daniel 9100: }
9101:
9102: /**
1.59 daniel 9103: * xmlRecoverDoc :
1.123 daniel 9104: * @cur: a pointer to an array of xmlChar
1.59 daniel 9105: *
9106: * parse an XML in-memory document and build a tree.
9107: * In the case the document is not Well Formed, a tree is built anyway
9108: *
1.68 daniel 9109: * Returns the resulting document tree
1.59 daniel 9110: */
9111:
1.69 daniel 9112: xmlDocPtr
1.123 daniel 9113: xmlRecoverDoc(xmlChar *cur) {
1.59 daniel 9114: return(xmlSAXParseDoc(NULL, cur, 1));
1.55 daniel 9115: }
9116:
9117: /**
1.69 daniel 9118: * xmlCreateFileParserCtxt :
1.50 daniel 9119: * @filename: the filename
9120: *
1.69 daniel 9121: * Create a parser context for a file content.
9122: * Automatic support for ZLIB/Compress compressed document is provided
9123: * by default if found at compile-time.
1.50 daniel 9124: *
1.69 daniel 9125: * Returns the new parser context or NULL
1.9 httpng 9126: */
1.69 daniel 9127: xmlParserCtxtPtr
9128: xmlCreateFileParserCtxt(const char *filename)
9129: {
9130: xmlParserCtxtPtr ctxt;
1.40 daniel 9131: xmlParserInputPtr inputStream;
1.91 daniel 9132: xmlParserInputBufferPtr buf;
1.111 daniel 9133: char *directory = NULL;
1.9 httpng 9134:
1.91 daniel 9135: buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
9136: if (buf == NULL) return(NULL);
1.9 httpng 9137:
1.97 daniel 9138: ctxt = xmlNewParserCtxt();
1.16 daniel 9139: if (ctxt == NULL) {
9140: return(NULL);
9141: }
1.97 daniel 9142:
1.96 daniel 9143: inputStream = xmlNewInputStream(ctxt);
1.40 daniel 9144: if (inputStream == NULL) {
1.97 daniel 9145: xmlFreeParserCtxt(ctxt);
1.40 daniel 9146: return(NULL);
9147: }
9148:
1.119 daniel 9149: inputStream->filename = xmlMemStrdup(filename);
1.91 daniel 9150: inputStream->buf = buf;
9151: inputStream->base = inputStream->buf->buffer->content;
9152: inputStream->cur = inputStream->buf->buffer->content;
1.16 daniel 9153:
1.40 daniel 9154: inputPush(ctxt, inputStream);
1.110 daniel 9155: if ((ctxt->directory == NULL) && (directory == NULL))
1.106 daniel 9156: directory = xmlParserGetDirectory(filename);
9157: if ((ctxt->directory == NULL) && (directory != NULL))
1.110 daniel 9158: ctxt->directory = directory;
1.106 daniel 9159:
1.69 daniel 9160: return(ctxt);
9161: }
9162:
9163: /**
9164: * xmlSAXParseFile :
9165: * @sax: the SAX handler block
9166: * @filename: the filename
9167: * @recovery: work in recovery mode, i.e. tries to read no Well Formed
9168: * documents
9169: *
9170: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9171: * compressed document is provided by default if found at compile-time.
9172: * It use the given SAX function block to handle the parsing callback.
9173: * If sax is NULL, fallback to the default DOM tree building routines.
9174: *
9175: * Returns the resulting document tree
9176: */
9177:
1.79 daniel 9178: xmlDocPtr
9179: xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
1.69 daniel 9180: int recovery) {
9181: xmlDocPtr ret;
9182: xmlParserCtxtPtr ctxt;
1.111 daniel 9183: char *directory = NULL;
1.69 daniel 9184:
9185: ctxt = xmlCreateFileParserCtxt(filename);
9186: if (ctxt == NULL) return(NULL);
1.74 daniel 9187: if (sax != NULL) {
1.93 veillard 9188: if (ctxt->sax != NULL)
1.119 daniel 9189: xmlFree(ctxt->sax);
1.74 daniel 9190: ctxt->sax = sax;
9191: ctxt->userData = NULL;
9192: }
1.106 daniel 9193:
1.110 daniel 9194: if ((ctxt->directory == NULL) && (directory == NULL))
1.106 daniel 9195: directory = xmlParserGetDirectory(filename);
9196: if ((ctxt->directory == NULL) && (directory != NULL))
1.156 daniel 9197: ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1.16 daniel 9198:
9199: xmlParseDocument(ctxt);
1.40 daniel 9200:
1.72 daniel 9201: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 9202: else {
9203: ret = NULL;
1.72 daniel 9204: xmlFreeDoc(ctxt->myDoc);
9205: ctxt->myDoc = NULL;
1.59 daniel 9206: }
1.86 daniel 9207: if (sax != NULL)
9208: ctxt->sax = NULL;
1.69 daniel 9209: xmlFreeParserCtxt(ctxt);
1.20 daniel 9210:
9211: return(ret);
9212: }
9213:
1.55 daniel 9214: /**
9215: * xmlParseFile :
9216: * @filename: the filename
9217: *
9218: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9219: * compressed document is provided by default if found at compile-time.
9220: *
1.68 daniel 9221: * Returns the resulting document tree
1.55 daniel 9222: */
9223:
1.79 daniel 9224: xmlDocPtr
9225: xmlParseFile(const char *filename) {
1.59 daniel 9226: return(xmlSAXParseFile(NULL, filename, 0));
9227: }
9228:
9229: /**
9230: * xmlRecoverFile :
9231: * @filename: the filename
9232: *
9233: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9234: * compressed document is provided by default if found at compile-time.
9235: * In the case the document is not Well Formed, a tree is built anyway
9236: *
1.68 daniel 9237: * Returns the resulting document tree
1.59 daniel 9238: */
9239:
1.79 daniel 9240: xmlDocPtr
9241: xmlRecoverFile(const char *filename) {
1.59 daniel 9242: return(xmlSAXParseFile(NULL, filename, 1));
1.55 daniel 9243: }
1.32 daniel 9244:
1.50 daniel 9245: /**
1.69 daniel 9246: * xmlCreateMemoryParserCtxt :
1.68 daniel 9247: * @buffer: an pointer to a char array
1.127 daniel 9248: * @size: the size of the array
1.50 daniel 9249: *
1.69 daniel 9250: * Create a parser context for an XML in-memory document.
1.50 daniel 9251: *
1.69 daniel 9252: * Returns the new parser context or NULL
1.20 daniel 9253: */
1.69 daniel 9254: xmlParserCtxtPtr
9255: xmlCreateMemoryParserCtxt(char *buffer, int size) {
1.20 daniel 9256: xmlParserCtxtPtr ctxt;
1.40 daniel 9257: xmlParserInputPtr input;
9258:
1.158 daniel 9259: if (buffer[size - 1] != 0)
9260: buffer[size - 1] = '\0';
1.40 daniel 9261:
1.97 daniel 9262: ctxt = xmlNewParserCtxt();
1.20 daniel 9263: if (ctxt == NULL) {
9264: return(NULL);
9265: }
1.97 daniel 9266:
1.96 daniel 9267: input = xmlNewInputStream(ctxt);
1.40 daniel 9268: if (input == NULL) {
1.97 daniel 9269: xmlFreeParserCtxt(ctxt);
1.40 daniel 9270: return(NULL);
9271: }
1.20 daniel 9272:
1.40 daniel 9273: input->filename = NULL;
9274: input->line = 1;
9275: input->col = 1;
1.96 daniel 9276: input->buf = NULL;
1.91 daniel 9277: input->consumed = 0;
1.75 daniel 9278:
1.116 daniel 9279: input->base = BAD_CAST buffer;
9280: input->cur = BAD_CAST buffer;
1.69 daniel 9281: input->free = NULL;
1.20 daniel 9282:
1.40 daniel 9283: inputPush(ctxt, input);
1.69 daniel 9284: return(ctxt);
9285: }
9286:
9287: /**
9288: * xmlSAXParseMemory :
9289: * @sax: the SAX handler block
9290: * @buffer: an pointer to a char array
1.127 daniel 9291: * @size: the size of the array
9292: * @recovery: work in recovery mode, i.e. tries to read not Well Formed
1.69 daniel 9293: * documents
9294: *
9295: * parse an XML in-memory block and use the given SAX function block
9296: * to handle the parsing callback. If sax is NULL, fallback to the default
9297: * DOM tree building routines.
9298: *
9299: * Returns the resulting document tree
9300: */
9301: xmlDocPtr
9302: xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
9303: xmlDocPtr ret;
9304: xmlParserCtxtPtr ctxt;
9305:
9306: ctxt = xmlCreateMemoryParserCtxt(buffer, size);
9307: if (ctxt == NULL) return(NULL);
1.74 daniel 9308: if (sax != NULL) {
9309: ctxt->sax = sax;
9310: ctxt->userData = NULL;
9311: }
1.20 daniel 9312:
9313: xmlParseDocument(ctxt);
1.40 daniel 9314:
1.72 daniel 9315: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 9316: else {
9317: ret = NULL;
1.72 daniel 9318: xmlFreeDoc(ctxt->myDoc);
9319: ctxt->myDoc = NULL;
1.59 daniel 9320: }
1.86 daniel 9321: if (sax != NULL)
9322: ctxt->sax = NULL;
1.69 daniel 9323: xmlFreeParserCtxt(ctxt);
1.16 daniel 9324:
1.9 httpng 9325: return(ret);
1.17 daniel 9326: }
9327:
1.55 daniel 9328: /**
9329: * xmlParseMemory :
1.68 daniel 9330: * @buffer: an pointer to a char array
1.55 daniel 9331: * @size: the size of the array
9332: *
9333: * parse an XML in-memory block and build a tree.
9334: *
1.68 daniel 9335: * Returns the resulting document tree
1.55 daniel 9336: */
9337:
9338: xmlDocPtr xmlParseMemory(char *buffer, int size) {
1.59 daniel 9339: return(xmlSAXParseMemory(NULL, buffer, size, 0));
9340: }
9341:
9342: /**
9343: * xmlRecoverMemory :
1.68 daniel 9344: * @buffer: an pointer to a char array
1.59 daniel 9345: * @size: the size of the array
9346: *
9347: * parse an XML in-memory block and build a tree.
9348: * In the case the document is not Well Formed, a tree is built anyway
9349: *
1.68 daniel 9350: * Returns the resulting document tree
1.59 daniel 9351: */
9352:
9353: xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
9354: return(xmlSAXParseMemory(NULL, buffer, size, 1));
1.17 daniel 9355: }
9356:
9357:
1.50 daniel 9358: /**
9359: * xmlSetupParserForBuffer:
9360: * @ctxt: an XML parser context
1.123 daniel 9361: * @buffer: a xmlChar * buffer
1.50 daniel 9362: * @filename: a file name
9363: *
1.19 daniel 9364: * Setup the parser context to parse a new buffer; Clears any prior
9365: * contents from the parser context. The buffer parameter must not be
9366: * NULL, but the filename parameter can be
9367: */
1.55 daniel 9368: void
1.123 daniel 9369: xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
1.17 daniel 9370: const char* filename)
9371: {
1.96 daniel 9372: xmlParserInputPtr input;
1.40 daniel 9373:
1.96 daniel 9374: input = xmlNewInputStream(ctxt);
9375: if (input == NULL) {
9376: perror("malloc");
1.119 daniel 9377: xmlFree(ctxt);
1.145 daniel 9378: return;
1.96 daniel 9379: }
9380:
9381: xmlClearParserCtxt(ctxt);
9382: if (filename != NULL)
1.119 daniel 9383: input->filename = xmlMemStrdup(filename);
1.96 daniel 9384: input->base = buffer;
9385: input->cur = buffer;
9386: inputPush(ctxt, input);
1.17 daniel 9387: }
9388:
1.123 daniel 9389: /**
9390: * xmlSAXUserParseFile:
9391: * @sax: a SAX handler
9392: * @user_data: The user data returned on SAX callbacks
9393: * @filename: a file name
9394: *
9395: * parse an XML file and call the given SAX handler routines.
9396: * Automatic support for ZLIB/Compress compressed document is provided
9397: *
9398: * Returns 0 in case of success or a error number otherwise
9399: */
1.131 daniel 9400: int
9401: xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
9402: const char *filename) {
1.123 daniel 9403: int ret = 0;
9404: xmlParserCtxtPtr ctxt;
9405:
9406: ctxt = xmlCreateFileParserCtxt(filename);
9407: if (ctxt == NULL) return -1;
1.134 daniel 9408: if (ctxt->sax != &xmlDefaultSAXHandler)
9409: xmlFree(ctxt->sax);
1.123 daniel 9410: ctxt->sax = sax;
1.140 daniel 9411: if (user_data != NULL)
9412: ctxt->userData = user_data;
1.123 daniel 9413:
9414: xmlParseDocument(ctxt);
9415:
9416: if (ctxt->wellFormed)
9417: ret = 0;
9418: else {
9419: if (ctxt->errNo != 0)
9420: ret = ctxt->errNo;
9421: else
9422: ret = -1;
9423: }
9424: if (sax != NULL)
9425: ctxt->sax = NULL;
9426: xmlFreeParserCtxt(ctxt);
9427:
9428: return ret;
9429: }
9430:
9431: /**
9432: * xmlSAXUserParseMemory:
9433: * @sax: a SAX handler
9434: * @user_data: The user data returned on SAX callbacks
9435: * @buffer: an in-memory XML document input
1.127 daniel 9436: * @size: the length of the XML document in bytes
1.123 daniel 9437: *
9438: * A better SAX parsing routine.
9439: * parse an XML in-memory buffer and call the given SAX handler routines.
9440: *
9441: * Returns 0 in case of success or a error number otherwise
9442: */
9443: int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
9444: char *buffer, int size) {
9445: int ret = 0;
9446: xmlParserCtxtPtr ctxt;
9447:
9448: ctxt = xmlCreateMemoryParserCtxt(buffer, size);
9449: if (ctxt == NULL) return -1;
9450: ctxt->sax = sax;
9451: ctxt->userData = user_data;
9452:
9453: xmlParseDocument(ctxt);
9454:
9455: if (ctxt->wellFormed)
9456: ret = 0;
9457: else {
9458: if (ctxt->errNo != 0)
9459: ret = ctxt->errNo;
9460: else
9461: ret = -1;
9462: }
9463: if (sax != NULL)
9464: ctxt->sax = NULL;
9465: xmlFreeParserCtxt(ctxt);
9466:
9467: return ret;
9468: }
9469:
1.32 daniel 9470:
1.98 daniel 9471: /************************************************************************
9472: * *
1.127 daniel 9473: * Miscellaneous *
1.98 daniel 9474: * *
9475: ************************************************************************/
9476:
1.132 daniel 9477: /**
9478: * xmlCleanupParser:
9479: *
9480: * Cleanup function for the XML parser. It tries to reclaim all
9481: * parsing related global memory allocated for the parser processing.
9482: * It doesn't deallocate any document related memory. Calling this
9483: * function should not prevent reusing the parser.
9484: */
9485:
9486: void
9487: xmlCleanupParser(void) {
9488: xmlCleanupCharEncodingHandlers();
1.133 daniel 9489: xmlCleanupPredefinedEntities();
1.132 daniel 9490: }
1.98 daniel 9491:
1.50 daniel 9492: /**
9493: * xmlParserFindNodeInfo:
9494: * @ctxt: an XML parser context
9495: * @node: an XML node within the tree
9496: *
9497: * Find the parser node info struct for a given node
9498: *
1.68 daniel 9499: * Returns an xmlParserNodeInfo block pointer or NULL
1.32 daniel 9500: */
9501: const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
9502: const xmlNode* node)
9503: {
9504: unsigned long pos;
9505:
9506: /* Find position where node should be at */
9507: pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
9508: if ( ctx->node_seq.buffer[pos].node == node )
9509: return &ctx->node_seq.buffer[pos];
9510: else
9511: return NULL;
9512: }
9513:
9514:
1.50 daniel 9515: /**
9516: * xmlInitNodeInfoSeq :
9517: * @seq: a node info sequence pointer
9518: *
9519: * -- Initialize (set to initial state) node info sequence
1.32 daniel 9520: */
1.55 daniel 9521: void
9522: xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32 daniel 9523: {
9524: seq->length = 0;
9525: seq->maximum = 0;
9526: seq->buffer = NULL;
9527: }
9528:
1.50 daniel 9529: /**
9530: * xmlClearNodeInfoSeq :
9531: * @seq: a node info sequence pointer
9532: *
9533: * -- Clear (release memory and reinitialize) node
1.32 daniel 9534: * info sequence
9535: */
1.55 daniel 9536: void
9537: xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32 daniel 9538: {
9539: if ( seq->buffer != NULL )
1.119 daniel 9540: xmlFree(seq->buffer);
1.32 daniel 9541: xmlInitNodeInfoSeq(seq);
9542: }
9543:
9544:
1.50 daniel 9545: /**
9546: * xmlParserFindNodeInfoIndex:
9547: * @seq: a node info sequence pointer
9548: * @node: an XML node pointer
9549: *
9550: *
1.32 daniel 9551: * xmlParserFindNodeInfoIndex : Find the index that the info record for
9552: * the given node is or should be at in a sorted sequence
1.68 daniel 9553: *
9554: * Returns a long indicating the position of the record
1.32 daniel 9555: */
9556: unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
9557: const xmlNode* node)
9558: {
9559: unsigned long upper, lower, middle;
9560: int found = 0;
9561:
9562: /* Do a binary search for the key */
9563: lower = 1;
9564: upper = seq->length;
9565: middle = 0;
9566: while ( lower <= upper && !found) {
9567: middle = lower + (upper - lower) / 2;
9568: if ( node == seq->buffer[middle - 1].node )
9569: found = 1;
9570: else if ( node < seq->buffer[middle - 1].node )
9571: upper = middle - 1;
9572: else
9573: lower = middle + 1;
9574: }
9575:
9576: /* Return position */
9577: if ( middle == 0 || seq->buffer[middle - 1].node < node )
9578: return middle;
9579: else
9580: return middle - 1;
9581: }
9582:
9583:
1.50 daniel 9584: /**
9585: * xmlParserAddNodeInfo:
9586: * @ctxt: an XML parser context
1.68 daniel 9587: * @info: a node info sequence pointer
1.50 daniel 9588: *
9589: * Insert node info record into the sorted sequence
1.32 daniel 9590: */
1.55 daniel 9591: void
9592: xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
1.68 daniel 9593: const xmlParserNodeInfo* info)
1.32 daniel 9594: {
9595: unsigned long pos;
9596: static unsigned int block_size = 5;
9597:
9598: /* Find pos and check to see if node is already in the sequence */
1.55 daniel 9599: pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
9600: if ( pos < ctxt->node_seq.length
9601: && ctxt->node_seq.buffer[pos].node == info->node ) {
9602: ctxt->node_seq.buffer[pos] = *info;
1.32 daniel 9603: }
9604:
9605: /* Otherwise, we need to add new node to buffer */
9606: else {
9607: /* Expand buffer by 5 if needed */
1.55 daniel 9608: if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
1.32 daniel 9609: xmlParserNodeInfo* tmp_buffer;
1.55 daniel 9610: unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
9611: *(ctxt->node_seq.maximum + block_size));
1.32 daniel 9612:
1.55 daniel 9613: if ( ctxt->node_seq.buffer == NULL )
1.119 daniel 9614: tmp_buffer = (xmlParserNodeInfo*) xmlMalloc(byte_size);
1.32 daniel 9615: else
1.119 daniel 9616: tmp_buffer = (xmlParserNodeInfo*) xmlRealloc(ctxt->node_seq.buffer, byte_size);
1.32 daniel 9617:
9618: if ( tmp_buffer == NULL ) {
1.55 daniel 9619: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 9620: ctxt->sax->error(ctxt->userData, "Out of memory\n");
1.123 daniel 9621: ctxt->errNo = XML_ERR_NO_MEMORY;
1.32 daniel 9622: return;
9623: }
1.55 daniel 9624: ctxt->node_seq.buffer = tmp_buffer;
9625: ctxt->node_seq.maximum += block_size;
1.32 daniel 9626: }
9627:
9628: /* If position is not at end, move elements out of the way */
1.55 daniel 9629: if ( pos != ctxt->node_seq.length ) {
1.32 daniel 9630: unsigned long i;
9631:
1.55 daniel 9632: for ( i = ctxt->node_seq.length; i > pos; i-- )
9633: ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
1.32 daniel 9634: }
9635:
9636: /* Copy element and increase length */
1.55 daniel 9637: ctxt->node_seq.buffer[pos] = *info;
9638: ctxt->node_seq.length++;
1.32 daniel 9639: }
9640: }
1.77 daniel 9641:
1.98 daniel 9642:
9643: /**
9644: * xmlSubstituteEntitiesDefault :
9645: * @val: int 0 or 1
9646: *
9647: * Set and return the previous value for default entity support.
9648: * Initially the parser always keep entity references instead of substituting
9649: * entity values in the output. This function has to be used to change the
9650: * default parser behaviour
9651: * SAX::subtituteEntities() has to be used for changing that on a file by
9652: * file basis.
9653: *
9654: * Returns the last value for 0 for no substitution, 1 for substitution.
9655: */
9656:
9657: int
9658: xmlSubstituteEntitiesDefault(int val) {
9659: int old = xmlSubstituteEntitiesDefaultValue;
9660:
9661: xmlSubstituteEntitiesDefaultValue = val;
9662: return(old);
9663: }
1.77 daniel 9664:
Webmaster