blob: 054f6308fda0c40c55d500dc4b89b316cb01ec53 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
Daniel Veillardb1059e22000-09-16 14:02:43 +00002 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3 * implemented on top of the SAX interfaces
Daniel Veillard260a68f1998-08-13 03:39:55 +00004 *
Daniel Veillarde0854c32000-08-27 21:12:29 +00005 * References:
6 * The XML specification:
7 * http://www.w3.org/TR/REC-xml
8 * Original 1.0 version:
9 * http://www.w3.org/TR/1998/REC-xml-19980210
10 * XML second edition working draft
11 * http://www.w3.org/TR/2000/WD-xml-2e-20000814
12 *
Daniel Veillardb1059e22000-09-16 14:02:43 +000013 * Okay this is a big file, the parser core is around 7000 lines, then it
14 * is followed by the progressive parser top routines, then the various
15 * high level APIs to call the parser and a few miscelaneous functions.
16 * A number of helper functions and deprecated ones have been moved to
17 * parserInternals.c to reduce this file size.
18 * As much as possible the functions are associated with their relative
19 * production in the XML specification. A few productions defining the
20 * different ranges of character are actually implanted either in
21 * parserInternals.h or parserInternals.c
22 * The DOM tree build is realized from the default SAX callbacks in
23 * the module SAX.c.
24 * The routines doing the validation checks are in valid.c and called either
25 * from the SAx callbacks or as standalones functions using a preparsed
26 * document.
27 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000028 * See Copyright for the status of this software.
29 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000030 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +000031 */
32
33#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000034#include "win32config.h"
Daniel Veillard39c7d712000-09-10 16:14:55 +000035#define XML_DIR_SEP '\\'
Daniel Veillard260a68f1998-08-13 03:39:55 +000036#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +000037#include "config.h"
Daniel Veillard39c7d712000-09-10 16:14:55 +000038#define XML_DIR_SEP '/'
Daniel Veillard260a68f1998-08-13 03:39:55 +000039#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000040
Daniel Veillard260a68f1998-08-13 03:39:55 +000041#include <stdio.h>
Daniel Veillardb71379b2000-10-09 12:30:39 +000042#include <stdlib.h>
Daniel Veillard32bc74e2000-07-14 14:49:25 +000043#include <string.h>
Daniel Veillardb71379b2000-10-09 12:30:39 +000044#include <libxml/xmlmemory.h>
45#include <libxml/tree.h>
46#include <libxml/parser.h>
47#include <libxml/parserInternals.h>
48#include <libxml/valid.h>
49#include <libxml/entities.h>
50#include <libxml/xmlerror.h>
51#include <libxml/encoding.h>
52#include <libxml/xmlIO.h>
53#include <libxml/uri.h>
54
Daniel Veillard7f7d1111999-09-22 09:46:25 +000055#ifdef HAVE_CTYPE_H
56#include <ctype.h>
57#endif
58#ifdef HAVE_STDLIB_H
Seth Alvese7f12e61998-10-01 20:51:15 +000059#include <stdlib.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000060#endif
61#ifdef HAVE_SYS_STAT_H
Daniel Veillard260a68f1998-08-13 03:39:55 +000062#include <sys/stat.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000063#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000064#ifdef HAVE_FCNTL_H
65#include <fcntl.h>
66#endif
67#ifdef HAVE_UNISTD_H
68#include <unistd.h>
69#endif
70#ifdef HAVE_ZLIB_H
71#include <zlib.h>
72#endif
73
Daniel Veillard260a68f1998-08-13 03:39:55 +000074
Daniel Veillarddbfd6411999-12-28 16:35:14 +000075#define XML_PARSER_BIG_BUFFER_SIZE 1000
76#define XML_PARSER_BUFFER_SIZE 100
77
Daniel Veillardb1059e22000-09-16 14:02:43 +000078/*
79 * Various global defaults for parsing
80 */
Daniel Veillardcf461992000-03-14 18:30:20 +000081int xmlGetWarningsDefaultValue = 1;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +000082int xmlParserDebugEntities = 0;
Daniel Veillardb1059e22000-09-16 14:02:43 +000083int xmlSubstituteEntitiesDefaultValue = 0;
84int xmlDoValidityCheckingDefaultValue = 0;
85int xmlPedanticParserDefaultValue = 0;
86int xmlKeepBlanksDefaultValue = 1;
Daniel Veillard14fff061999-06-22 21:49:07 +000087
Daniel Veillard3c558c31999-12-22 11:30:41 +000088/*
89 * List of XML prefixed PI allowed by W3C specs
90 */
91
92const char *xmlW3CPIs[] = {
93 "xml-stylesheet",
94 NULL
95};
Daniel Veillarde2d034d1999-07-27 19:52:06 +000096
Daniel Veillardb1059e22000-09-16 14:02:43 +000097/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
Daniel Veillardcf461992000-03-14 18:30:20 +000098void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
99xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
100 const xmlChar **str);
Daniel Veillardbe803962000-06-28 23:40:59 +0000101
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000102
Daniel Veillard260a68f1998-08-13 03:39:55 +0000103/************************************************************************
104 * *
105 * Parser stacks related functions and macros *
106 * *
107 ************************************************************************/
Daniel Veillard011b63c1999-06-02 17:44:04 +0000108
Daniel Veillard10a2c651999-12-12 13:03:50 +0000109xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
110 const xmlChar ** str);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000111
Daniel Veillard260a68f1998-08-13 03:39:55 +0000112/*
113 * Generic function for accessing stacks in the Parser Context
114 */
115
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000116#define PUSH_AND_POP(scope, type, name) \
117scope int name##Push(xmlParserCtxtPtr ctxt, type value) { \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000118 if (ctxt->name##Nr >= ctxt->name##Max) { \
119 ctxt->name##Max *= 2; \
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000120 ctxt->name##Tab = (type *) xmlRealloc(ctxt->name##Tab, \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000121 ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
122 if (ctxt->name##Tab == NULL) { \
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000123 xmlGenericError(xmlGenericErrorContext, \
124 "realloc failed !\n"); \
Daniel Veillard0142b842000-01-14 14:45:24 +0000125 return(0); \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000126 } \
127 } \
128 ctxt->name##Tab[ctxt->name##Nr] = value; \
129 ctxt->name = value; \
130 return(ctxt->name##Nr++); \
131} \
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000132scope type name##Pop(xmlParserCtxtPtr ctxt) { \
Daniel Veillardd692aa41999-02-28 21:54:31 +0000133 type ret; \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000134 if (ctxt->name##Nr <= 0) return(0); \
135 ctxt->name##Nr--; \
Daniel Veillardccb09631998-10-27 06:21:04 +0000136 if (ctxt->name##Nr > 0) \
137 ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \
138 else \
139 ctxt->name = NULL; \
Daniel Veillardd692aa41999-02-28 21:54:31 +0000140 ret = ctxt->name##Tab[ctxt->name##Nr]; \
141 ctxt->name##Tab[ctxt->name##Nr] = 0; \
142 return(ret); \
Daniel Veillard260a68f1998-08-13 03:39:55 +0000143} \
144
Daniel Veillardb1059e22000-09-16 14:02:43 +0000145/*
146 * Those macros actually generate the functions
147 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000148PUSH_AND_POP(extern, xmlParserInputPtr, input)
149PUSH_AND_POP(extern, xmlNodePtr, node)
150PUSH_AND_POP(extern, xmlChar*, name)
Daniel Veillard260a68f1998-08-13 03:39:55 +0000151
Daniel Veillardcf461992000-03-14 18:30:20 +0000152int spacePush(xmlParserCtxtPtr ctxt, int val) {
153 if (ctxt->spaceNr >= ctxt->spaceMax) {
154 ctxt->spaceMax *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000155 ctxt->spaceTab = (int *) xmlRealloc(ctxt->spaceTab,
Daniel Veillardcf461992000-03-14 18:30:20 +0000156 ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
157 if (ctxt->spaceTab == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000158 xmlGenericError(xmlGenericErrorContext,
159 "realloc failed !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000160 return(0);
161 }
162 }
163 ctxt->spaceTab[ctxt->spaceNr] = val;
164 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
165 return(ctxt->spaceNr++);
166}
167
168int spacePop(xmlParserCtxtPtr ctxt) {
169 int ret;
170 if (ctxt->spaceNr <= 0) return(0);
171 ctxt->spaceNr--;
172 if (ctxt->spaceNr > 0)
173 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
174 else
175 ctxt->space = NULL;
176 ret = ctxt->spaceTab[ctxt->spaceNr];
177 ctxt->spaceTab[ctxt->spaceNr] = -1;
178 return(ret);
179}
180
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000181/*
182 * Macros for accessing the content. Those should be used only by the parser,
183 * and not exported.
184 *
Daniel Veillardb1059e22000-09-16 14:02:43 +0000185 * Dirty macros, i.e. one often need to make assumption on the context to
186 * use them
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000187 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000188 * CUR_PTR return the current pointer to the xmlChar to be parsed.
Daniel Veillardcf461992000-03-14 18:30:20 +0000189 * To be used with extreme caution since operations consuming
190 * characters may move the input buffer to a different location !
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000191 * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled
Daniel Veillardcf461992000-03-14 18:30:20 +0000192 * This should be used internally by the parser
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000193 * only to compare to ASCII values otherwise it would break when
194 * running with UTF-8 encoding.
Daniel Veillardb1059e22000-09-16 14:02:43 +0000195 * RAW same as CUR but in the input buffer, bypass any token
196 * extraction that may have been done
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000197 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000198 * to compare on ASCII based substring.
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000199 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000200 * strings within the parser.
201 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000202 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000203 *
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000204 * NEXT Skip to the next character, this does the proper decoding
205 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
Daniel Veillardb1059e22000-09-16 14:02:43 +0000206 * NEXTL(l) Skip l xmlChars in the input buffer
207 * CUR_CHAR(l) returns the current unicode character (int), set l
208 * to the number of xmlChars used for the encoding [0-5].
209 * CUR_SCHAR same but operate on a string instead of the context
210 * COPY_BUF copy the current unicode char to the target buffer, increment
211 * the index
212 * GROW, SHRINK handling of input buffers
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000213 */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000214
Daniel Veillardcf461992000-03-14 18:30:20 +0000215#define RAW (ctxt->token ? -1 : (*ctxt->input->cur))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000216#define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000217#define NXT(val) ctxt->input->cur[(val)]
218#define CUR_PTR ctxt->input->cur
Daniel Veillardcf461992000-03-14 18:30:20 +0000219
Daniel Veillard126f2792000-10-24 17:10:12 +0000220#define SKIP(val) do { \
221 ctxt->nbChars += (val),ctxt->input->cur += (val); \
Daniel Veillardcf461992000-03-14 18:30:20 +0000222 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
Daniel Veillardb1059e22000-09-16 14:02:43 +0000223 /* DEPR if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); */\
Daniel Veillardcf461992000-03-14 18:30:20 +0000224 if ((*ctxt->input->cur == 0) && \
225 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
Daniel Veillard126f2792000-10-24 17:10:12 +0000226 xmlPopInput(ctxt); \
227 } while (0)
Daniel Veillardcf461992000-03-14 18:30:20 +0000228
Daniel Veillard126f2792000-10-24 17:10:12 +0000229#define SHRINK do { \
230 xmlParserInputShrink(ctxt->input); \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000231 if ((*ctxt->input->cur == 0) && \
232 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
Daniel Veillard126f2792000-10-24 17:10:12 +0000233 xmlPopInput(ctxt); \
234 } while (0)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000235
Daniel Veillard126f2792000-10-24 17:10:12 +0000236#define GROW do { \
237 xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000238 if ((*ctxt->input->cur == 0) && \
239 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
Daniel Veillard126f2792000-10-24 17:10:12 +0000240 xmlPopInput(ctxt); \
241 } while (0)
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000242
Daniel Veillard126f2792000-10-24 17:10:12 +0000243#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000244
Daniel Veillard126f2792000-10-24 17:10:12 +0000245#define NEXT xmlNextChar(ctxt)
Daniel Veillardcf461992000-03-14 18:30:20 +0000246
Daniel Veillard126f2792000-10-24 17:10:12 +0000247#define NEXTL(l) do { \
Daniel Veillardcf461992000-03-14 18:30:20 +0000248 if (*(ctxt->input->cur) == '\n') { \
249 ctxt->input->line++; ctxt->input->col = 1; \
250 } else ctxt->input->col++; \
251 ctxt->token = 0; ctxt->input->cur += l; \
Daniel Veillardb05deb71999-08-10 19:04:08 +0000252 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
Daniel Veillard126f2792000-10-24 17:10:12 +0000253 /* DEPR if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); */\
254 } while (0)
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000255
Daniel Veillard126f2792000-10-24 17:10:12 +0000256#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
257#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
Daniel Veillardcf461992000-03-14 18:30:20 +0000258
259#define COPY_BUF(l,b,i,v) \
260 if (l == 1) b[i++] = (xmlChar) v; \
Daniel Veillard126f2792000-10-24 17:10:12 +0000261 else i += xmlCopyChar(l,&b[i],v)
Daniel Veillardcf461992000-03-14 18:30:20 +0000262
263/**
Daniel Veillardcf461992000-03-14 18:30:20 +0000264 * xmlSkipBlankChars:
265 * @ctxt: the XML parser context
266 *
267 * skip all blanks character found at that point in the input streams.
268 * It pops up finished entities in the process if allowable at that point.
269 *
270 * Returns the number of space chars skipped
271 */
272
273int
274xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
275 int cur, res = 0;
276
Daniel Veillarde0854c32000-08-27 21:12:29 +0000277 /*
278 * It's Okay to use CUR/NEXT here since all the blanks are on
279 * the ASCII range.
280 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000281 do {
282 cur = CUR;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000283 while (IS_BLANK(cur)) { /* CHECKED tstblanks.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +0000284 NEXT;
285 cur = CUR;
286 res++;
287 }
288 while ((cur == 0) && (ctxt->inputNr > 1) &&
289 (ctxt->instate != XML_PARSER_COMMENT)) {
290 xmlPopInput(ctxt);
291 cur = CUR;
292 }
Daniel Veillarde0854c32000-08-27 21:12:29 +0000293 /*
294 * Need to handle support of entities branching here
295 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000296 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
Daniel Veillardb1059e22000-09-16 14:02:43 +0000297 /* DEPR if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); */
Daniel Veillarde0854c32000-08-27 21:12:29 +0000298 } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +0000299 return(res);
300}
Daniel Veillard260a68f1998-08-13 03:39:55 +0000301
Daniel Veillardb05deb71999-08-10 19:04:08 +0000302/************************************************************************
303 * *
Daniel Veillardb1059e22000-09-16 14:02:43 +0000304 * Commodity functions to handle entities *
Daniel Veillardb05deb71999-08-10 19:04:08 +0000305 * *
306 ************************************************************************/
Daniel Veillard260a68f1998-08-13 03:39:55 +0000307
Daniel Veillard11e00581998-10-24 18:27:49 +0000308/**
309 * xmlPopInput:
310 * @ctxt: an XML parser context
311 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000312 * xmlPopInput: the current input pointed by ctxt->input came to an end
313 * pop it and return the next char.
314 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000315 * Returns the current xmlChar in the parser context
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000317xmlChar
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000318xmlPopInput(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000319 if (ctxt->inputNr == 1) return(0); /* End of main Input */
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000320 if (xmlParserDebugEntities)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000321 xmlGenericError(xmlGenericErrorContext,
322 "Popping input %d\n", ctxt->inputNr);
Daniel Veillardbc50b591999-03-01 12:28:53 +0000323 xmlFreeInputStream(inputPop(ctxt));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000324 if ((*ctxt->input->cur == 0) &&
325 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
326 return(xmlPopInput(ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000327 return(CUR);
328}
329
Daniel Veillard11e00581998-10-24 18:27:49 +0000330/**
331 * xmlPushInput:
332 * @ctxt: an XML parser context
333 * @input: an XML parser input fragment (entity, XML fragment ...).
334 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000335 * xmlPushInput: switch to a new input stream which is stacked on top
336 * of the previous one(s).
337 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000338void
339xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000340 if (input == NULL) return;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000341
342 if (xmlParserDebugEntities) {
343 if ((ctxt->input != NULL) && (ctxt->input->filename))
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000344 xmlGenericError(xmlGenericErrorContext,
345 "%s(%d): ", ctxt->input->filename,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000346 ctxt->input->line);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000347 xmlGenericError(xmlGenericErrorContext,
348 "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000349 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000350 inputPush(ctxt, input);
Daniel Veillardcf461992000-03-14 18:30:20 +0000351 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000352}
353
Daniel Veillard11e00581998-10-24 18:27:49 +0000354/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000355 * xmlParseCharRef:
356 * @ctxt: an XML parser context
357 *
358 * parse Reference declarations
359 *
360 * [66] CharRef ::= '&#' [0-9]+ ';' |
361 * '&#x' [0-9a-fA-F]+ ';'
362 *
363 * [ WFC: Legal Character ]
364 * Characters referred to using character references must match the
365 * production for Char.
366 *
Daniel Veillard10a2c651999-12-12 13:03:50 +0000367 * Returns the value parsed (as an int), 0 in case of error
Daniel Veillardb05deb71999-08-10 19:04:08 +0000368 */
369int
370xmlParseCharRef(xmlParserCtxtPtr ctxt) {
371 int val = 0;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000372 int count = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000373
374 if (ctxt->token != 0) {
375 val = ctxt->token;
376 ctxt->token = 0;
377 return(val);
378 }
Daniel Veillarde0854c32000-08-27 21:12:29 +0000379 /*
380 * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
381 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000382 if ((RAW == '&') && (NXT(1) == '#') &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000383 (NXT(2) == 'x')) {
384 SKIP(3);
Daniel Veillarde0854c32000-08-27 21:12:29 +0000385 GROW;
386 while (RAW != ';') { /* loop blocked by count */
387 if ((RAW >= '0') && (RAW <= '9') && (count < 20))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000388 val = val * 16 + (CUR - '0');
Daniel Veillarde0854c32000-08-27 21:12:29 +0000389 else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000390 val = val * 16 + (CUR - 'a') + 10;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000391 else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000392 val = val * 16 + (CUR - 'A') + 10;
393 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000394 ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000395 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
396 ctxt->sax->error(ctxt->userData,
397 "xmlParseCharRef: invalid hexadecimal value\n");
398 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000399 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000400 val = 0;
401 break;
402 }
403 NEXT;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000404 count++;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000405 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000406 if (RAW == ';') {
407 /* on purpose to avoid reentrancy problems with NEXT and SKIP */
408 ctxt->nbChars ++;
409 ctxt->input->cur++;
410 }
411 } else if ((RAW == '&') && (NXT(1) == '#')) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000412 SKIP(2);
Daniel Veillarde0854c32000-08-27 21:12:29 +0000413 GROW;
414 while (RAW != ';') { /* loop blocked by count */
415 if ((RAW >= '0') && (RAW <= '9') && (count < 20))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000416 val = val * 10 + (CUR - '0');
417 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000418 ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000419 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
420 ctxt->sax->error(ctxt->userData,
421 "xmlParseCharRef: invalid decimal value\n");
422 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000423 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000424 val = 0;
425 break;
426 }
427 NEXT;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000428 count++;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000429 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000430 if (RAW == ';') {
431 /* on purpose to avoid reentrancy problems with NEXT and SKIP */
432 ctxt->nbChars ++;
433 ctxt->input->cur++;
434 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000435 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000436 ctxt->errNo = XML_ERR_INVALID_CHARREF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000437 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
438 ctxt->sax->error(ctxt->userData,
439 "xmlParseCharRef: invalid value\n");
440 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000441 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000442 }
443
444 /*
445 * [ WFC: Legal Character ]
446 * Characters referred to using character references must match the
447 * production for Char.
448 */
449 if (IS_CHAR(val)) {
450 return(val);
451 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000452 ctxt->errNo = XML_ERR_INVALID_CHAR;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000453 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000454 ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
Daniel Veillardb05deb71999-08-10 19:04:08 +0000455 val);
456 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000457 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000458 }
459 return(0);
460}
461
462/**
Daniel Veillard10a2c651999-12-12 13:03:50 +0000463 * xmlParseStringCharRef:
464 * @ctxt: an XML parser context
465 * @str: a pointer to an index in the string
466 *
467 * parse Reference declarations, variant parsing from a string rather
468 * than an an input flow.
469 *
470 * [66] CharRef ::= '&#' [0-9]+ ';' |
471 * '&#x' [0-9a-fA-F]+ ';'
472 *
473 * [ WFC: Legal Character ]
474 * Characters referred to using character references must match the
475 * production for Char.
476 *
477 * Returns the value parsed (as an int), 0 in case of error, str will be
478 * updated to the current value of the index
479 */
480int
481xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
482 const xmlChar *ptr;
483 xmlChar cur;
484 int val = 0;
485
486 if ((str == NULL) || (*str == NULL)) return(0);
487 ptr = *str;
488 cur = *ptr;
Daniel Veillard0caf07a1999-12-21 16:25:49 +0000489 if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000490 ptr += 3;
491 cur = *ptr;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000492 while (cur != ';') { /* Non input consuming loop */
Daniel Veillard10a2c651999-12-12 13:03:50 +0000493 if ((cur >= '0') && (cur <= '9'))
494 val = val * 16 + (cur - '0');
495 else if ((cur >= 'a') && (cur <= 'f'))
496 val = val * 16 + (cur - 'a') + 10;
497 else if ((cur >= 'A') && (cur <= 'F'))
498 val = val * 16 + (cur - 'A') + 10;
499 else {
500 ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
501 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
502 ctxt->sax->error(ctxt->userData,
Daniel Veillardbe803962000-06-28 23:40:59 +0000503 "xmlParseStringCharRef: invalid hexadecimal value\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +0000504 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000505 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000506 val = 0;
507 break;
508 }
509 ptr++;
510 cur = *ptr;
511 }
512 if (cur == ';')
513 ptr++;
Daniel Veillard0142b842000-01-14 14:45:24 +0000514 } else if ((cur == '&') && (ptr[1] == '#')){
Daniel Veillard10a2c651999-12-12 13:03:50 +0000515 ptr += 2;
516 cur = *ptr;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000517 while (cur != ';') { /* Non input consuming loops */
Daniel Veillard10a2c651999-12-12 13:03:50 +0000518 if ((cur >= '0') && (cur <= '9'))
519 val = val * 10 + (cur - '0');
520 else {
521 ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
522 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
523 ctxt->sax->error(ctxt->userData,
Daniel Veillardbe803962000-06-28 23:40:59 +0000524 "xmlParseStringCharRef: invalid decimal value\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +0000525 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000526 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000527 val = 0;
528 break;
529 }
530 ptr++;
531 cur = *ptr;
532 }
533 if (cur == ';')
534 ptr++;
535 } else {
536 ctxt->errNo = XML_ERR_INVALID_CHARREF;
537 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
538 ctxt->sax->error(ctxt->userData,
539 "xmlParseCharRef: invalid value\n");
540 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000541 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000542 return(0);
543 }
544 *str = ptr;
545
546 /*
547 * [ WFC: Legal Character ]
548 * Characters referred to using character references must match the
549 * production for Char.
550 */
551 if (IS_CHAR(val)) {
552 return(val);
553 } else {
554 ctxt->errNo = XML_ERR_INVALID_CHAR;
555 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
556 ctxt->sax->error(ctxt->userData,
557 "CharRef: invalid xmlChar value %d\n", val);
558 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000559 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000560 }
561 return(0);
562}
563
564/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000565 * xmlParserHandlePEReference:
566 * @ctxt: the parser context
567 *
568 * [69] PEReference ::= '%' Name ';'
569 *
570 * [ WFC: No Recursion ]
Daniel Veillardb1059e22000-09-16 14:02:43 +0000571 * A parsed entity must not contain a recursive
Daniel Veillardb05deb71999-08-10 19:04:08 +0000572 * reference to itself, either directly or indirectly.
573 *
574 * [ WFC: Entity Declared ]
575 * In a document without any DTD, a document with only an internal DTD
576 * subset which contains no parameter entity references, or a document
577 * with "standalone='yes'", ... ... The declaration of a parameter
578 * entity must precede any reference to it...
579 *
580 * [ VC: Entity Declared ]
581 * In a document with an external subset or external parameter entities
582 * with "standalone='no'", ... ... The declaration of a parameter entity
583 * must precede any reference to it...
584 *
585 * [ WFC: In DTD ]
586 * Parameter-entity references may only appear in the DTD.
587 * NOTE: misleading but this is handled.
588 *
589 * A PEReference may have been detected in the current input stream
590 * the handling is done accordingly to
591 * http://www.w3.org/TR/REC-xml#entproc
592 * i.e.
593 * - Included in literal in entity values
594 * - Included as Paraemeter Entity reference within DTDs
595 */
596void
597xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000598 xmlChar *name;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000599 xmlEntityPtr entity = NULL;
600 xmlParserInputPtr input;
601
Daniel Veillard35008381999-10-25 13:15:52 +0000602 if (ctxt->token != 0) {
Daniel Veillard35008381999-10-25 13:15:52 +0000603 return;
604 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000605 if (RAW != '%') return;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000606 switch(ctxt->instate) {
607 case XML_PARSER_CDATA_SECTION:
608 return;
609 case XML_PARSER_COMMENT:
610 return;
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000611 case XML_PARSER_START_TAG:
612 return;
613 case XML_PARSER_END_TAG:
614 return;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000615 case XML_PARSER_EOF:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000616 ctxt->errNo = XML_ERR_PEREF_AT_EOF;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000617 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
618 ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
619 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000620 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000621 return;
622 case XML_PARSER_PROLOG:
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000623 case XML_PARSER_START:
624 case XML_PARSER_MISC:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000625 ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000626 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
627 ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
628 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000629 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000630 return;
631 case XML_PARSER_ENTITY_DECL:
632 case XML_PARSER_CONTENT:
633 case XML_PARSER_ATTRIBUTE_VALUE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000634 case XML_PARSER_PI:
Daniel Veillardcf461992000-03-14 18:30:20 +0000635 case XML_PARSER_SYSTEM_LITERAL:
Daniel Veillardb05deb71999-08-10 19:04:08 +0000636 /* we just ignore it there */
637 return;
638 case XML_PARSER_EPILOG:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000639 ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000640 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
641 ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
642 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000643 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000644 return;
645 case XML_PARSER_ENTITY_VALUE:
646 /*
647 * NOTE: in the case of entity values, we don't do the
Daniel Veillard51e3b151999-11-12 17:02:31 +0000648 * substitution here since we need the literal
Daniel Veillardb05deb71999-08-10 19:04:08 +0000649 * entity value to be able to save the internal
650 * subset of the document.
Daniel Veillarde0854c32000-08-27 21:12:29 +0000651 * This will be handled by xmlStringDecodeEntities
Daniel Veillardb05deb71999-08-10 19:04:08 +0000652 */
653 return;
654 case XML_PARSER_DTD:
655 /*
656 * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
657 * In the internal DTD subset, parameter-entity references
658 * can occur only where markup declarations can occur, not
659 * within markup declarations.
660 * In that case this is handled in xmlParseMarkupDecl
661 */
662 if ((ctxt->external == 0) && (ctxt->inputNr == 1))
663 return;
664 }
665
666 NEXT;
667 name = xmlParseName(ctxt);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000668 if (xmlParserDebugEntities)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000669 xmlGenericError(xmlGenericErrorContext,
670 "PE Reference: %s\n", name);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000671 if (name == NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000672 ctxt->errNo = XML_ERR_PEREF_NO_NAME;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000673 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
674 ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
675 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000676 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000677 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +0000678 if (RAW == ';') {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000679 NEXT;
680 if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
681 entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
682 if (entity == NULL) {
683
684 /*
685 * [ WFC: Entity Declared ]
686 * In a document without any DTD, a document with only an
687 * internal DTD subset which contains no parameter entity
688 * references, or a document with "standalone='yes'", ...
689 * ... The declaration of a parameter entity must precede
690 * any reference to it...
691 */
692 if ((ctxt->standalone == 1) ||
693 ((ctxt->hasExternalSubset == 0) &&
694 (ctxt->hasPErefs == 0))) {
695 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
696 ctxt->sax->error(ctxt->userData,
697 "PEReference: %%%s; not found\n", name);
698 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000699 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000700 } else {
701 /*
702 * [ VC: Entity Declared ]
703 * In a document with an external subset or external
704 * parameter entities with "standalone='no'", ...
705 * ... The declaration of a parameter entity must precede
706 * any reference to it...
707 */
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000708 if ((!ctxt->disableSAX) &&
709 (ctxt->validate) && (ctxt->vctxt.error != NULL)) {
Daniel Veillard87b95392000-08-12 21:12:04 +0000710 ctxt->vctxt.error(ctxt->vctxt.userData,
711 "PEReference: %%%s; not found\n", name);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000712 } else if ((!ctxt->disableSAX) &&
713 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +0000714 ctxt->sax->warning(ctxt->userData,
715 "PEReference: %%%s; not found\n", name);
716 ctxt->valid = 0;
717 }
718 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +0000719 if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
720 (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000721 /*
Daniel Veillardb1059e22000-09-16 14:02:43 +0000722 * handle the extra spaces added before and after
Daniel Veillardb05deb71999-08-10 19:04:08 +0000723 * c.f. http://www.w3.org/TR/REC-xml#as-PE
Daniel Veillardb1059e22000-09-16 14:02:43 +0000724 * this is done independantly.
Daniel Veillardb05deb71999-08-10 19:04:08 +0000725 */
726 input = xmlNewEntityInputStream(ctxt, entity);
727 xmlPushInput(ctxt, input);
Daniel Veillardcf461992000-03-14 18:30:20 +0000728 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
729 (RAW == '<') && (NXT(1) == '?') &&
730 (NXT(2) == 'x') && (NXT(3) == 'm') &&
731 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
732 xmlParseTextDecl(ctxt);
733 }
734 if (ctxt->token == 0)
735 ctxt->token = ' ';
Daniel Veillardb05deb71999-08-10 19:04:08 +0000736 } else {
737 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
738 ctxt->sax->error(ctxt->userData,
739 "xmlHandlePEReference: %s is not a parameter entity\n",
740 name);
741 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000742 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000743 }
744 }
745 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000746 ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000747 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
748 ctxt->sax->error(ctxt->userData,
749 "xmlHandlePEReference: expecting ';'\n");
750 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000751 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000752 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000753 xmlFree(name);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000754 }
755}
756
Daniel Veillard011b63c1999-06-02 17:44:04 +0000757/*
758 * Macro used to grow the current buffer.
759 */
760#define growBuffer(buffer) { \
761 buffer##_size *= 2; \
Daniel Veillard0142b842000-01-14 14:45:24 +0000762 buffer = (xmlChar *) \
763 xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
Daniel Veillard011b63c1999-06-02 17:44:04 +0000764 if (buffer == NULL) { \
765 perror("realloc failed"); \
Daniel Veillard0142b842000-01-14 14:45:24 +0000766 return(NULL); \
Daniel Veillard011b63c1999-06-02 17:44:04 +0000767 } \
768}
769
Daniel Veillard011b63c1999-06-02 17:44:04 +0000770/**
Daniel Veillard10a2c651999-12-12 13:03:50 +0000771 * xmlStringDecodeEntities:
772 * @ctxt: the parser context
773 * @str: the input string
774 * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
775 * @end: an end marker xmlChar, 0 if none
776 * @end2: an end marker xmlChar, 0 if none
777 * @end3: an end marker xmlChar, 0 if none
778 *
Daniel Veillarde0854c32000-08-27 21:12:29 +0000779 * Takes a entity string content and process to do the adequate subtitutions.
780 *
Daniel Veillard10a2c651999-12-12 13:03:50 +0000781 * [67] Reference ::= EntityRef | CharRef
782 *
783 * [69] PEReference ::= '%' Name ';'
784 *
785 * Returns A newly allocated string with the substitution done. The caller
786 * must deallocate it !
787 */
788xmlChar *
789xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
790 xmlChar end, xmlChar end2, xmlChar end3) {
791 xmlChar *buffer = NULL;
792 int buffer_size = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000793
794 xmlChar *current = NULL;
795 xmlEntityPtr ent;
Daniel Veillardcf461992000-03-14 18:30:20 +0000796 int c,l;
797 int nbchars = 0;
798
Daniel Veillard87b95392000-08-12 21:12:04 +0000799 if (str == NULL)
800 return(NULL);
801
Daniel Veillardcf461992000-03-14 18:30:20 +0000802 if (ctxt->depth > 40) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +0000803 ctxt->errNo = XML_ERR_ENTITY_LOOP;
Daniel Veillardcf461992000-03-14 18:30:20 +0000804 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
805 ctxt->sax->error(ctxt->userData,
806 "Detected entity reference loop\n");
807 ctxt->wellFormed = 0;
808 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000809 return(NULL);
810 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000811
812 /*
813 * allocate a translation buffer.
814 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000815 buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000816 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
817 if (buffer == NULL) {
818 perror("xmlDecodeEntities: malloc failed");
819 return(NULL);
820 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000821
822 /*
823 * Ok loop until we reach one of the ending char or a size limit.
Daniel Veillarde0854c32000-08-27 21:12:29 +0000824 * we are operating on already parsed values.
Daniel Veillard10a2c651999-12-12 13:03:50 +0000825 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000826 c = CUR_SCHAR(str, l);
Daniel Veillarde0854c32000-08-27 21:12:29 +0000827 while ((c != 0) && (c != end) && /* non input consuming loop */
828 (c != end2) && (c != end3)) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000829
Daniel Veillardcf461992000-03-14 18:30:20 +0000830 if (c == 0) break;
831 if ((c == '&') && (str[1] == '#')) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000832 int val = xmlParseStringCharRef(ctxt, &str);
Daniel Veillardcf461992000-03-14 18:30:20 +0000833 if (val != 0) {
834 COPY_BUF(0,buffer,nbchars,val);
835 }
836 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000837 if (xmlParserDebugEntities)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000838 xmlGenericError(xmlGenericErrorContext,
839 "String decoding Entity Reference: %.30s\n",
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000840 str);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000841 ent = xmlParseStringEntityRef(ctxt, &str);
Daniel Veillarde0854c32000-08-27 21:12:29 +0000842 if ((ent != NULL) &&
843 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
Daniel Veillard52402ce2000-08-22 23:36:12 +0000844 if (ent->content != NULL) {
845 COPY_BUF(0,buffer,nbchars,ent->content[0]);
846 } else {
847 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
848 ctxt->sax->error(ctxt->userData,
849 "internal error entity has no content\n");
850 }
851 } else if ((ent != NULL) && (ent->content != NULL)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000852 xmlChar *rep;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000853
Daniel Veillardcf461992000-03-14 18:30:20 +0000854 ctxt->depth++;
855 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
856 0, 0, 0);
857 ctxt->depth--;
858 if (rep != NULL) {
859 current = rep;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000860 while (*current != 0) { /* non input consuming loop */
Daniel Veillardcf461992000-03-14 18:30:20 +0000861 buffer[nbchars++] = *current++;
862 if (nbchars >
863 buffer_size - XML_PARSER_BUFFER_SIZE) {
864 growBuffer(buffer);
865 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000866 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000867 xmlFree(rep);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000868 }
869 } else if (ent != NULL) {
870 int i = xmlStrlen(ent->name);
871 const xmlChar *cur = ent->name;
872
Daniel Veillardcf461992000-03-14 18:30:20 +0000873 buffer[nbchars++] = '&';
874 if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000875 growBuffer(buffer);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000876 }
877 for (;i > 0;i--)
Daniel Veillardcf461992000-03-14 18:30:20 +0000878 buffer[nbchars++] = *cur++;
879 buffer[nbchars++] = ';';
Daniel Veillard10a2c651999-12-12 13:03:50 +0000880 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000881 } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000882 if (xmlParserDebugEntities)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000883 xmlGenericError(xmlGenericErrorContext,
884 "String decoding PE Reference: %.30s\n", str);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000885 ent = xmlParseStringPEReference(ctxt, &str);
886 if (ent != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000887 xmlChar *rep;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000888
Daniel Veillardcf461992000-03-14 18:30:20 +0000889 ctxt->depth++;
890 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
891 0, 0, 0);
892 ctxt->depth--;
893 if (rep != NULL) {
894 current = rep;
Daniel Veillarde0854c32000-08-27 21:12:29 +0000895 while (*current != 0) { /* non input consuming loop */
Daniel Veillardcf461992000-03-14 18:30:20 +0000896 buffer[nbchars++] = *current++;
897 if (nbchars >
898 buffer_size - XML_PARSER_BUFFER_SIZE) {
899 growBuffer(buffer);
900 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000901 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000902 xmlFree(rep);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000903 }
904 }
905 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +0000906 COPY_BUF(l,buffer,nbchars,c);
907 str += l;
908 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000909 growBuffer(buffer);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000910 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000911 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000912 c = CUR_SCHAR(str, l);
Daniel Veillard10a2c651999-12-12 13:03:50 +0000913 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000914 buffer[nbchars++] = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000915 return(buffer);
916}
917
Daniel Veillard260a68f1998-08-13 03:39:55 +0000918
919/************************************************************************
920 * *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000921 * Commodity functions to handle xmlChars *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000922 * *
923 ************************************************************************/
924
Daniel Veillard11e00581998-10-24 18:27:49 +0000925/**
926 * xmlStrndup:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000927 * @cur: the input xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +0000928 * @len: the len of @cur
929 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000930 * a strndup for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +0000931 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000932 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000933 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000934xmlChar *
935xmlStrndup(const xmlChar *cur, int len) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000936 xmlChar *ret;
937
938 if ((cur == NULL) || (len < 0)) return(NULL);
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000939 ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000940 if (ret == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000941 xmlGenericError(xmlGenericErrorContext,
942 "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000943 (len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000944 return(NULL);
945 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000946 memcpy(ret, cur, len * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000947 ret[len] = 0;
948 return(ret);
949}
950
Daniel Veillard11e00581998-10-24 18:27:49 +0000951/**
952 * xmlStrdup:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000953 * @cur: the input xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +0000954 *
Daniel Veillardcf461992000-03-14 18:30:20 +0000955 * a strdup for array of xmlChar's. Since they are supposed to be
956 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
957 * a termination mark of '0'.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000958 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000959 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000960 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000961xmlChar *
962xmlStrdup(const xmlChar *cur) {
963 const xmlChar *p = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000964
Daniel Veillard10a2c651999-12-12 13:03:50 +0000965 if (cur == NULL) return(NULL);
Daniel Veillarde0854c32000-08-27 21:12:29 +0000966 while (*p != 0) p++; /* non input consuming */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000967 return(xmlStrndup(cur, p - cur));
968}
969
Daniel Veillard11e00581998-10-24 18:27:49 +0000970/**
971 * xmlCharStrndup:
972 * @cur: the input char *
973 * @len: the len of @cur
974 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000975 * a strndup for char's to xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +0000976 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000977 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000978 */
979
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000980xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000981xmlCharStrndup(const char *cur, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000982 int i;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000983 xmlChar *ret;
984
985 if ((cur == NULL) || (len < 0)) return(NULL);
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000986 ret = (xmlChar *) xmlMalloc((len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000987 if (ret == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000988 xmlGenericError(xmlGenericErrorContext, "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000989 (len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 return(NULL);
991 }
992 for (i = 0;i < len;i++)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000993 ret[i] = (xmlChar) cur[i];
Daniel Veillard260a68f1998-08-13 03:39:55 +0000994 ret[len] = 0;
995 return(ret);
996}
997
Daniel Veillard11e00581998-10-24 18:27:49 +0000998/**
999 * xmlCharStrdup:
1000 * @cur: the input char *
1001 * @len: the len of @cur
1002 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001003 * a strdup for char's to xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001004 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001005 * Returns a new xmlChar * or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001006 */
1007
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001008xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001009xmlCharStrdup(const char *cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001010 const char *p = cur;
1011
Daniel Veillard10a2c651999-12-12 13:03:50 +00001012 if (cur == NULL) return(NULL);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001013 while (*p != '\0') p++; /* non input consuming */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001014 return(xmlCharStrndup(cur, p - cur));
1015}
1016
Daniel Veillard11e00581998-10-24 18:27:49 +00001017/**
1018 * xmlStrcmp:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001019 * @str1: the first xmlChar *
1020 * @str2: the second xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001021 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001022 * a strcmp for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001023 *
1024 * Returns the integer result of the comparison
Daniel Veillard260a68f1998-08-13 03:39:55 +00001025 */
1026
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001027int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001028xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029 register int tmp;
1030
Daniel Veillardb1059e22000-09-16 14:02:43 +00001031 if (str1 == str2) return(0);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001032 if (str1 == NULL) return(-1);
1033 if (str2 == NULL) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001034 do {
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001035 tmp = *str1++ - *str2;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001036 if (tmp != 0) return(tmp);
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001037 } while (*str2++ != 0);
1038 return 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039}
1040
Daniel Veillard11e00581998-10-24 18:27:49 +00001041/**
Daniel Veillard8b5dd832000-10-01 20:28:44 +00001042 * xmlStrEqual:
1043 * @str1: the first xmlChar *
1044 * @str2: the second xmlChar *
1045 *
1046 * Check if both string are equal of have same content
1047 * Should be a bit more readable and faster than xmlStrEqual()
1048 *
1049 * Returns 1 if they are equal, 0 if they are different
1050 */
1051
1052int
1053xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
1054 if (str1 == str2) return(1);
1055 if (str1 == NULL) return(0);
1056 if (str2 == NULL) return(0);
1057 do {
1058 if (*str1++ != *str2) return(0);
1059 } while (*str2++);
1060 return(1);
1061}
1062
1063/**
Daniel Veillard11e00581998-10-24 18:27:49 +00001064 * xmlStrncmp:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001065 * @str1: the first xmlChar *
1066 * @str2: the second xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001067 * @len: the max comparison length
1068 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001069 * a strncmp for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001070 *
1071 * Returns the integer result of the comparison
Daniel Veillard260a68f1998-08-13 03:39:55 +00001072 */
1073
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001074int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001075xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001076 register int tmp;
1077
1078 if (len <= 0) return(0);
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001079 if (str1 == str2) return(0);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001080 if (str1 == NULL) return(-1);
1081 if (str2 == NULL) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001082 do {
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001083 tmp = *str1++ - *str2;
1084 if (tmp != 0 || --len == 0) return(tmp);
1085 } while (*str2++ != 0);
1086 return 0;
1087}
1088
1089static xmlChar casemap[256] = {
1090 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1091 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
1092 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
1093 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
1094 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
1095 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
1096 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
1097 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
1098 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
1099 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
1100 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
1101 0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
1102 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
1103 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
1104 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
1105 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
1106 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
1107 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
1108 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
1109 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
1110 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
1111 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
1112 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
1113 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
1114 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
1115 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
1116 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
1117 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
1118 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
1119 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
1120 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
1121 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
1122};
1123
1124/**
1125 * xmlStrcasecmp:
1126 * @str1: the first xmlChar *
1127 * @str2: the second xmlChar *
1128 *
1129 * a strcasecmp for xmlChar's
1130 *
1131 * Returns the integer result of the comparison
1132 */
1133
1134int
1135xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) {
1136 register int tmp;
1137
1138 if (str1 == str2) return(0);
1139 if (str1 == NULL) return(-1);
1140 if (str2 == NULL) return(1);
1141 do {
1142 tmp = casemap[*str1++] - casemap[*str2];
Daniel Veillard260a68f1998-08-13 03:39:55 +00001143 if (tmp != 0) return(tmp);
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001144 } while (*str2++ != 0);
1145 return 0;
1146}
1147
1148/**
1149 * xmlStrncasecmp:
1150 * @str1: the first xmlChar *
1151 * @str2: the second xmlChar *
1152 * @len: the max comparison length
1153 *
1154 * a strncasecmp for xmlChar's
1155 *
1156 * Returns the integer result of the comparison
1157 */
1158
1159int
1160xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) {
1161 register int tmp;
1162
1163 if (len <= 0) return(0);
1164 if (str1 == str2) return(0);
1165 if (str1 == NULL) return(-1);
1166 if (str2 == NULL) return(1);
1167 do {
1168 tmp = casemap[*str1++] - casemap[*str2];
1169 if (tmp != 0 || --len == 0) return(tmp);
1170 } while (*str2++ != 0);
1171 return 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172}
1173
Daniel Veillard11e00581998-10-24 18:27:49 +00001174/**
1175 * xmlStrchr:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001176 * @str: the xmlChar * array
1177 * @val: the xmlChar to search
Daniel Veillard11e00581998-10-24 18:27:49 +00001178 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001179 * a strchr for xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001180 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001181 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001182 */
1183
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001184const xmlChar *
1185xmlStrchr(const xmlChar *str, xmlChar val) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001186 if (str == NULL) return(NULL);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001187 while (*str != 0) { /* non input consuming */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001188 if (*str == val) return((xmlChar *) str);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001189 str++;
1190 }
1191 return(NULL);
1192}
1193
Daniel Veillard11e00581998-10-24 18:27:49 +00001194/**
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001195 * xmlStrstr:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001196 * @str: the xmlChar * array (haystack)
1197 * @val: the xmlChar to search (needle)
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001198 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001199 * a strstr for xmlChar's
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001200 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001201 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001202 */
1203
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001204const xmlChar *
1205xmlStrstr(const xmlChar *str, xmlChar *val) {
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001206 int n;
1207
1208 if (str == NULL) return(NULL);
1209 if (val == NULL) return(NULL);
1210 n = xmlStrlen(val);
1211
1212 if (n == 0) return(str);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001213 while (*str != 0) { /* non input consuming */
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001214 if (*str == *val) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001215 if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001216 }
1217 str++;
1218 }
1219 return(NULL);
1220}
1221
1222/**
Daniel Veillardb656ebe2000-09-22 13:51:48 +00001223 * xmlStrcasestr:
1224 * @str: the xmlChar * array (haystack)
1225 * @val: the xmlChar to search (needle)
1226 *
1227 * a case-ignoring strstr for xmlChar's
1228 *
1229 * Returns the xmlChar * for the first occurence or NULL.
1230 */
1231
1232const xmlChar *
1233xmlStrcasestr(const xmlChar *str, xmlChar *val) {
1234 int n;
1235
1236 if (str == NULL) return(NULL);
1237 if (val == NULL) return(NULL);
1238 n = xmlStrlen(val);
1239
1240 if (n == 0) return(str);
1241 while (*str != 0) { /* non input consuming */
1242 if (casemap[*str] == casemap[*val])
1243 if (!xmlStrncasecmp(str, val, n)) return(str);
1244 str++;
1245 }
1246 return(NULL);
1247}
1248
1249/**
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001250 * xmlStrsub:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001251 * @str: the xmlChar * array (haystack)
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001252 * @start: the index of the first char (zero based)
1253 * @len: the length of the substring
1254 *
1255 * Extract a substring of a given string
1256 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001257 * Returns the xmlChar * for the first occurence or NULL.
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001258 */
1259
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001260xmlChar *
1261xmlStrsub(const xmlChar *str, int start, int len) {
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001262 int i;
1263
1264 if (str == NULL) return(NULL);
1265 if (start < 0) return(NULL);
1266 if (len < 0) return(NULL);
1267
1268 for (i = 0;i < start;i++) {
1269 if (*str == 0) return(NULL);
1270 str++;
1271 }
1272 if (*str == 0) return(NULL);
1273 return(xmlStrndup(str, len));
1274}
1275
1276/**
Daniel Veillard11e00581998-10-24 18:27:49 +00001277 * xmlStrlen:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001278 * @str: the xmlChar * array
Daniel Veillard11e00581998-10-24 18:27:49 +00001279 *
Daniel Veillard51e3b151999-11-12 17:02:31 +00001280 * length of a xmlChar's string
Daniel Veillard1e346af1999-02-22 10:33:01 +00001281 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001282 * Returns the number of xmlChar contained in the ARRAY.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001283 */
1284
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001285int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001286xmlStrlen(const xmlChar *str) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001287 int len = 0;
1288
1289 if (str == NULL) return(0);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001290 while (*str != 0) { /* non input consuming */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001291 str++;
1292 len++;
1293 }
1294 return(len);
1295}
1296
Daniel Veillard11e00581998-10-24 18:27:49 +00001297/**
1298 * xmlStrncat:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001299 * @cur: the original xmlChar * array
1300 * @add: the xmlChar * array added
Daniel Veillard11e00581998-10-24 18:27:49 +00001301 * @len: the length of @add
1302 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001303 * a strncat for array of xmlChar's
Daniel Veillard1e346af1999-02-22 10:33:01 +00001304 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001305 * Returns a new xmlChar * containing the concatenated string.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001306 */
1307
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001308xmlChar *
1309xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001310 int size;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001311 xmlChar *ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001312
1313 if ((add == NULL) || (len == 0))
1314 return(cur);
1315 if (cur == NULL)
1316 return(xmlStrndup(add, len));
1317
1318 size = xmlStrlen(cur);
Daniel Veillard32bc74e2000-07-14 14:49:25 +00001319 ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001320 if (ret == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001321 xmlGenericError(xmlGenericErrorContext,
1322 "xmlStrncat: realloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001323 (size + len + 1) * (long)sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001324 return(cur);
1325 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001326 memcpy(&ret[size], add, len * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001327 ret[size + len] = 0;
1328 return(ret);
1329}
1330
Daniel Veillard11e00581998-10-24 18:27:49 +00001331/**
1332 * xmlStrcat:
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001333 * @cur: the original xmlChar * array
1334 * @add: the xmlChar * array added
Daniel Veillard11e00581998-10-24 18:27:49 +00001335 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001336 * a strcat for array of xmlChar's. Since they are supposed to be
1337 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
1338 * a termination mark of '0'.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001339 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001340 * Returns a new xmlChar * containing the concatenated string.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001341 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001342xmlChar *
1343xmlStrcat(xmlChar *cur, const xmlChar *add) {
1344 const xmlChar *p = add;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001345
1346 if (add == NULL) return(cur);
1347 if (cur == NULL)
1348 return(xmlStrdup(add));
1349
Daniel Veillarde0854c32000-08-27 21:12:29 +00001350 while (*p != 0) p++; /* non input consuming */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001351 return(xmlStrncat(cur, add, p - add));
1352}
1353
1354/************************************************************************
1355 * *
1356 * Commodity functions, cleanup needed ? *
1357 * *
1358 ************************************************************************/
1359
Daniel Veillard11e00581998-10-24 18:27:49 +00001360/**
1361 * areBlanks:
1362 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001363 * @str: a xmlChar *
Daniel Veillard11e00581998-10-24 18:27:49 +00001364 * @len: the size of @str
1365 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001366 * Is this a sequence of blank chars that one can ignore ?
Daniel Veillard11e00581998-10-24 18:27:49 +00001367 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001368 * Returns 1 if ignorable 0 otherwise.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001369 */
1370
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001371static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001372 int i, ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001373 xmlNodePtr lastChild;
1374
Daniel Veillard83a30e72000-03-02 03:33:32 +00001375 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001376 * Check for xml:space value.
1377 */
1378 if (*(ctxt->space) == 1)
1379 return(0);
1380
1381 /*
Daniel Veillard83a30e72000-03-02 03:33:32 +00001382 * Check that the string is made of blanks
1383 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001384 for (i = 0;i < len;i++)
1385 if (!(IS_BLANK(str[i]))) return(0);
1386
Daniel Veillard83a30e72000-03-02 03:33:32 +00001387 /*
1388 * Look if the element is mixed content in the Dtd if available
1389 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00001390 if (ctxt->myDoc != NULL) {
1391 ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
1392 if (ret == 0) return(1);
1393 if (ret == 1) return(0);
1394 }
Daniel Veillard83a30e72000-03-02 03:33:32 +00001395
Daniel Veillardb05deb71999-08-10 19:04:08 +00001396 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001397 * Otherwise, heuristic :-\
Daniel Veillardb05deb71999-08-10 19:04:08 +00001398 */
Daniel Veillard83a30e72000-03-02 03:33:32 +00001399 if (ctxt->keepBlanks)
1400 return(0);
Daniel Veillardcf461992000-03-14 18:30:20 +00001401 if (RAW != '<') return(0);
Daniel Veillard83a30e72000-03-02 03:33:32 +00001402 if (ctxt->node == NULL) return(0);
Daniel Veillardcf461992000-03-14 18:30:20 +00001403 if ((ctxt->node->children == NULL) &&
1404 (RAW == '<') && (NXT(1) == '/')) return(0);
Daniel Veillard83a30e72000-03-02 03:33:32 +00001405
Daniel Veillard260a68f1998-08-13 03:39:55 +00001406 lastChild = xmlGetLastChild(ctxt->node);
1407 if (lastChild == NULL) {
Daniel Veillard90fb02c2000-03-02 03:46:43 +00001408 if (ctxt->node->content != NULL) return(0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001409 } else if (xmlNodeIsText(lastChild))
Daniel Veillard90fb02c2000-03-02 03:46:43 +00001410 return(0);
Daniel Veillardcf461992000-03-14 18:30:20 +00001411 else if ((ctxt->node->children != NULL) &&
1412 (xmlNodeIsText(ctxt->node->children)))
Daniel Veillard90fb02c2000-03-02 03:46:43 +00001413 return(0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001414 return(1);
1415}
1416
Daniel Veillard260a68f1998-08-13 03:39:55 +00001417/*
1418 * Forward definition for recusive behaviour.
1419 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00001420void xmlParsePEReference(xmlParserCtxtPtr ctxt);
1421void xmlParseReference(xmlParserCtxtPtr ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422
1423/************************************************************************
1424 * *
1425 * Extra stuff for namespace support *
1426 * Relates to http://www.w3.org/TR/WD-xml-names *
1427 * *
1428 ************************************************************************/
1429
Daniel Veillard11e00581998-10-24 18:27:49 +00001430/**
Daniel Veillarde0854c32000-08-27 21:12:29 +00001431 * xmlSplitQName:
1432 * @ctxt: an XML parser context
1433 * @name: an XML parser context
1434 * @prefix: a xmlChar **
1435 *
1436 * parse an UTF8 encoded XML qualified name string
1437 *
1438 * [NS 5] QName ::= (Prefix ':')? LocalPart
1439 *
1440 * [NS 6] Prefix ::= NCName
1441 *
1442 * [NS 7] LocalPart ::= NCName
1443 *
1444 * Returns the local part, and prefix is updated
1445 * to get the Prefix if any.
1446 */
1447
1448xmlChar *
1449xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
1450 xmlChar buf[XML_MAX_NAMELEN + 5];
1451 xmlChar *buffer = NULL;
1452 int len = 0;
1453 int max = XML_MAX_NAMELEN;
1454 xmlChar *ret = NULL;
1455 const xmlChar *cur = name;
1456 int c;
1457
1458 *prefix = NULL;
1459
1460 /* xml: prefix is not really a namespace */
1461 if ((cur[0] == 'x') && (cur[1] == 'm') &&
1462 (cur[2] == 'l') && (cur[3] == ':'))
1463 return(xmlStrdup(name));
1464
1465 /* nasty but valid */
1466 if (cur[0] == ':')
1467 return(xmlStrdup(name));
1468
1469 c = *cur++;
1470 while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
1471 buf[len++] = c;
1472 c = *cur++;
1473 }
1474 if (len >= max) {
1475 /*
1476 * Okay someone managed to make a huge name, so he's ready to pay
1477 * for the processing speed.
1478 */
1479 max = len * 2;
1480
1481 buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
1482 if (buffer == NULL) {
1483 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1484 ctxt->sax->error(ctxt->userData,
1485 "xmlSplitQName: out of memory\n");
1486 return(NULL);
1487 }
1488 memcpy(buffer, buf, len);
1489 while ((c != 0) && (c != ':')) { /* tested bigname.xml */
1490 if (len + 10 > max) {
1491 max *= 2;
1492 buffer = (xmlChar *) xmlRealloc(buffer,
1493 max * sizeof(xmlChar));
1494 if (buffer == NULL) {
1495 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1496 ctxt->sax->error(ctxt->userData,
1497 "xmlSplitQName: out of memory\n");
1498 return(NULL);
1499 }
1500 }
1501 buffer[len++] = c;
1502 c = *cur++;
1503 }
1504 buffer[len] = 0;
1505 }
1506
1507 if (buffer == NULL)
1508 ret = xmlStrndup(buf, len);
1509 else {
1510 ret = buffer;
1511 buffer = NULL;
1512 max = XML_MAX_NAMELEN;
1513 }
1514
1515
1516 if (c == ':') {
1517 c = *cur++;
1518 if (c == 0) return(ret);
1519 *prefix = ret;
1520 len = 0;
1521
1522 while ((c != 0) && (len < max)) { /* tested bigname2.xml */
1523 buf[len++] = c;
1524 c = *cur++;
1525 }
1526 if (len >= max) {
1527 /*
1528 * Okay someone managed to make a huge name, so he's ready to pay
1529 * for the processing speed.
1530 */
1531 max = len * 2;
1532
1533 buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
1534 if (buffer == NULL) {
1535 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1536 ctxt->sax->error(ctxt->userData,
1537 "xmlSplitQName: out of memory\n");
1538 return(NULL);
1539 }
1540 memcpy(buffer, buf, len);
1541 while (c != 0) { /* tested bigname2.xml */
1542 if (len + 10 > max) {
1543 max *= 2;
1544 buffer = (xmlChar *) xmlRealloc(buffer,
1545 max * sizeof(xmlChar));
1546 if (buffer == NULL) {
1547 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1548 ctxt->sax->error(ctxt->userData,
1549 "xmlSplitQName: out of memory\n");
1550 return(NULL);
1551 }
1552 }
1553 buffer[len++] = c;
1554 c = *cur++;
1555 }
1556 buffer[len] = 0;
1557 }
1558
1559 if (buffer == NULL)
1560 ret = xmlStrndup(buf, len);
1561 else {
1562 ret = buffer;
1563 }
1564 }
1565
1566 return(ret);
1567}
1568
Daniel Veillard260a68f1998-08-13 03:39:55 +00001569/************************************************************************
1570 * *
1571 * The parser itself *
1572 * Relates to http://www.w3.org/TR/REC-xml *
1573 * *
1574 ************************************************************************/
1575
Daniel Veillard11e00581998-10-24 18:27:49 +00001576/**
1577 * xmlParseName:
1578 * @ctxt: an XML parser context
1579 *
1580 * parse an XML name.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581 *
1582 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1583 * CombiningChar | Extender
1584 *
1585 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1586 *
1587 * [6] Names ::= Name (S Name)*
Daniel Veillard1e346af1999-02-22 10:33:01 +00001588 *
1589 * Returns the Name parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001590 */
1591
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001592xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001593xmlParseName(xmlParserCtxtPtr ctxt) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001594 xmlChar buf[XML_MAX_NAMELEN + 5];
1595 int len = 0, l;
1596 int c;
Daniel Veillarde0854c32000-08-27 21:12:29 +00001597 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001598
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001599 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00001600 c = CUR_CHAR(l);
Daniel Veillard5e873c42000-04-12 13:27:38 +00001601 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
1602 (!IS_LETTER(c) && (c != '_') &&
1603 (c != ':'))) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001604 return(NULL);
1605 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001606
Daniel Veillarde0854c32000-08-27 21:12:29 +00001607 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
Daniel Veillard5e873c42000-04-12 13:27:38 +00001608 ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
1609 (c == '.') || (c == '-') ||
1610 (c == '_') || (c == ':') ||
1611 (IS_COMBINING(c)) ||
1612 (IS_EXTENDER(c)))) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001613 if (count++ > 100) {
1614 count = 0;
1615 GROW;
1616 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001617 COPY_BUF(l,buf,len,c);
1618 NEXTL(l);
1619 c = CUR_CHAR(l);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001620 if (len >= XML_MAX_NAMELEN) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001621 /*
1622 * Okay someone managed to make a huge name, so he's ready to pay
1623 * for the processing speed.
1624 */
1625 xmlChar *buffer;
1626 int max = len * 2;
1627
1628 buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
1629 if (buffer == NULL) {
1630 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1631 ctxt->sax->error(ctxt->userData,
1632 "xmlParseName: out of memory\n");
1633 return(NULL);
1634 }
1635 memcpy(buffer, buf, len);
1636 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +00001637 (c == '.') || (c == '-') ||
1638 (c == '_') || (c == ':') ||
1639 (IS_COMBINING(c)) ||
1640 (IS_EXTENDER(c))) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001641 if (count++ > 100) {
1642 count = 0;
1643 GROW;
1644 }
1645 if (len + 10 > max) {
1646 max *= 2;
1647 buffer = (xmlChar *) xmlRealloc(buffer,
1648 max * sizeof(xmlChar));
1649 if (buffer == NULL) {
1650 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1651 ctxt->sax->error(ctxt->userData,
1652 "xmlParseName: out of memory\n");
1653 return(NULL);
1654 }
1655 }
1656 COPY_BUF(l,buffer,len,c);
Daniel Veillardcf461992000-03-14 18:30:20 +00001657 NEXTL(l);
1658 c = CUR_CHAR(l);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001659 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00001660 buffer[len] = 0;
1661 return(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001662 }
1663 }
1664 return(xmlStrndup(buf, len));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001665}
1666
Daniel Veillard11e00581998-10-24 18:27:49 +00001667/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00001668 * xmlParseStringName:
1669 * @ctxt: an XML parser context
Daniel Veillardb1059e22000-09-16 14:02:43 +00001670 * @str: a pointer to the string pointer (IN/OUT)
Daniel Veillard10a2c651999-12-12 13:03:50 +00001671 *
1672 * parse an XML name.
1673 *
1674 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1675 * CombiningChar | Extender
1676 *
1677 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
1678 *
1679 * [6] Names ::= Name (S Name)*
1680 *
1681 * Returns the Name parsed or NULL. The str pointer
1682 * is updated to the current location in the string.
1683 */
1684
1685xmlChar *
1686xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001687 xmlChar buf[XML_MAX_NAMELEN + 5];
1688 const xmlChar *cur = *str;
1689 int len = 0, l;
1690 int c;
Daniel Veillard10a2c651999-12-12 13:03:50 +00001691
Daniel Veillardcf461992000-03-14 18:30:20 +00001692 c = CUR_SCHAR(cur, l);
1693 if (!IS_LETTER(c) && (c != '_') &&
1694 (c != ':')) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001695 return(NULL);
1696 }
1697
Daniel Veillarde0854c32000-08-27 21:12:29 +00001698 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +00001699 (c == '.') || (c == '-') ||
1700 (c == '_') || (c == ':') ||
1701 (IS_COMBINING(c)) ||
1702 (IS_EXTENDER(c))) {
1703 COPY_BUF(l,buf,len,c);
1704 cur += l;
1705 c = CUR_SCHAR(cur, l);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001706 if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
1707 /*
1708 * Okay someone managed to make a huge name, so he's ready to pay
1709 * for the processing speed.
1710 */
1711 xmlChar *buffer;
1712 int max = len * 2;
1713
1714 buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
1715 if (buffer == NULL) {
1716 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1717 ctxt->sax->error(ctxt->userData,
1718 "xmlParseStringName: out of memory\n");
1719 return(NULL);
1720 }
1721 memcpy(buffer, buf, len);
1722 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +00001723 (c == '.') || (c == '-') ||
1724 (c == '_') || (c == ':') ||
1725 (IS_COMBINING(c)) ||
1726 (IS_EXTENDER(c))) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001727 if (len + 10 > max) {
1728 max *= 2;
1729 buffer = (xmlChar *) xmlRealloc(buffer,
1730 max * sizeof(xmlChar));
1731 if (buffer == NULL) {
1732 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1733 ctxt->sax->error(ctxt->userData,
1734 "xmlParseStringName: out of memory\n");
1735 return(NULL);
1736 }
1737 }
1738 COPY_BUF(l,buffer,len,c);
Daniel Veillardcf461992000-03-14 18:30:20 +00001739 cur += l;
1740 c = CUR_SCHAR(cur, l);
1741 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00001742 buffer[len] = 0;
1743 *str = cur;
1744 return(buffer);
Daniel Veillardcf461992000-03-14 18:30:20 +00001745 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00001746 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001747 *str = cur;
1748 return(xmlStrndup(buf, len));
Daniel Veillard10a2c651999-12-12 13:03:50 +00001749}
1750
1751/**
Daniel Veillard11e00581998-10-24 18:27:49 +00001752 * xmlParseNmtoken:
1753 * @ctxt: an XML parser context
1754 *
1755 * parse an XML Nmtoken.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001756 *
1757 * [7] Nmtoken ::= (NameChar)+
1758 *
1759 * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
Daniel Veillard1e346af1999-02-22 10:33:01 +00001760 *
1761 * Returns the Nmtoken parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001762 */
1763
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001764xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00001765xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001766 xmlChar buf[XML_MAX_NAMELEN + 5];
1767 int len = 0, l;
1768 int c;
1769 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001770
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001771 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00001772 c = CUR_CHAR(l);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001773
1774 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +00001775 (c == '.') || (c == '-') ||
1776 (c == '_') || (c == ':') ||
1777 (IS_COMBINING(c)) ||
1778 (IS_EXTENDER(c))) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001779 if (count++ > 100) {
1780 count = 0;
1781 GROW;
1782 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001783 COPY_BUF(l,buf,len,c);
1784 NEXTL(l);
1785 c = CUR_CHAR(l);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001786 if (len >= XML_MAX_NAMELEN) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001787 /*
1788 * Okay someone managed to make a huge token, so he's ready to pay
1789 * for the processing speed.
1790 */
1791 xmlChar *buffer;
1792 int max = len * 2;
1793
1794 buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
1795 if (buffer == NULL) {
1796 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1797 ctxt->sax->error(ctxt->userData,
1798 "xmlParseNmtoken: out of memory\n");
1799 return(NULL);
1800 }
1801 memcpy(buffer, buf, len);
1802 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */
Daniel Veillardcf461992000-03-14 18:30:20 +00001803 (c == '.') || (c == '-') ||
1804 (c == '_') || (c == ':') ||
1805 (IS_COMBINING(c)) ||
1806 (IS_EXTENDER(c))) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001807 if (count++ > 100) {
1808 count = 0;
1809 GROW;
1810 }
1811 if (len + 10 > max) {
1812 max *= 2;
1813 buffer = (xmlChar *) xmlRealloc(buffer,
1814 max * sizeof(xmlChar));
1815 if (buffer == NULL) {
1816 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1817 ctxt->sax->error(ctxt->userData,
1818 "xmlParseName: out of memory\n");
1819 return(NULL);
1820 }
1821 }
1822 COPY_BUF(l,buffer,len,c);
Daniel Veillardcf461992000-03-14 18:30:20 +00001823 NEXTL(l);
1824 c = CUR_CHAR(l);
1825 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00001826 buffer[len] = 0;
1827 return(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001828 }
1829 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001830 if (len == 0)
1831 return(NULL);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00001832 return(xmlStrndup(buf, len));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001833}
1834
Daniel Veillard11e00581998-10-24 18:27:49 +00001835/**
1836 * xmlParseEntityValue:
1837 * @ctxt: an XML parser context
Daniel Veillard011b63c1999-06-02 17:44:04 +00001838 * @orig: if non-NULL store a copy of the original entity value
Daniel Veillard11e00581998-10-24 18:27:49 +00001839 *
Daniel Veillardb1059e22000-09-16 14:02:43 +00001840 * parse a value for ENTITY declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00001841 *
1842 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
1843 * "'" ([^%&'] | PEReference | Reference)* "'"
Daniel Veillard1e346af1999-02-22 10:33:01 +00001844 *
Daniel Veillard011b63c1999-06-02 17:44:04 +00001845 * Returns the EntityValue parsed with reference substitued or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00001846 */
1847
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001848xmlChar *
1849xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001850 xmlChar *buf = NULL;
1851 int len = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001852 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001853 int c, l;
Daniel Veillard10a2c651999-12-12 13:03:50 +00001854 xmlChar stop;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001855 xmlChar *ret = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001856 const xmlChar *cur = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001857 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001858
Daniel Veillardcf461992000-03-14 18:30:20 +00001859 if (RAW == '"') stop = '"';
1860 else if (RAW == '\'') stop = '\'';
Daniel Veillard10a2c651999-12-12 13:03:50 +00001861 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001862 ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00001863 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00001864 ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001865 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00001866 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00001867 return(NULL);
1868 }
1869 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
1870 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001871 xmlGenericError(xmlGenericErrorContext,
1872 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001873 return(NULL);
1874 }
1875
1876 /*
1877 * The content of the entity definition is copied in a buffer.
1878 */
1879
1880 ctxt->instate = XML_PARSER_ENTITY_VALUE;
1881 input = ctxt->input;
1882 GROW;
1883 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00001884 c = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001885 /*
1886 * NOTE: 4.4.5 Included in Literal
1887 * When a parameter entity reference appears in a literal entity
1888 * value, ... a single or double quote character in the replacement
1889 * text is always treated as a normal data character and will not
1890 * terminate the literal.
1891 * In practice it means we stop the loop only when back at parsing
1892 * the initial entity and the quote is found
1893 */
Daniel Veillarde0854c32000-08-27 21:12:29 +00001894 while ((IS_CHAR(c)) && ((c != stop) || /* checked */
1895 (ctxt->input != input))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001896 if (len + 5 >= size) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001897 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00001898 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00001899 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001900 xmlGenericError(xmlGenericErrorContext,
1901 "realloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001902 return(NULL);
1903 }
1904 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001905 COPY_BUF(l,buf,len,c);
1906 NEXTL(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001907 /*
1908 * Pop-up of finished entities.
1909 */
Daniel Veillarde0854c32000-08-27 21:12:29 +00001910 while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
Daniel Veillard10a2c651999-12-12 13:03:50 +00001911 xmlPopInput(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00001912
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001913 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00001914 c = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001915 if (c == 0) {
1916 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00001917 c = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001918 }
1919 }
1920 buf[len] = 0;
1921
1922 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001923 * Raise problem w.r.t. '&' and '%' being used in non-entities
1924 * reference constructs. Note Charref will be handled in
1925 * xmlStringDecodeEntities()
1926 */
1927 cur = buf;
Daniel Veillard4948eb42000-08-29 09:41:15 +00001928 while (*cur != 0) { /* non input consuming */
Daniel Veillardcf461992000-03-14 18:30:20 +00001929 if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
1930 xmlChar *name;
1931 xmlChar tmp = *cur;
1932
1933 cur++;
1934 name = xmlParseStringName(ctxt, &cur);
1935 if ((name == NULL) || (*cur != ';')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00001936 ctxt->errNo = XML_ERR_ENTITY_CHAR_ERROR;
Daniel Veillardcf461992000-03-14 18:30:20 +00001937 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1938 ctxt->sax->error(ctxt->userData,
1939 "EntityValue: '%c' forbidden except for entities references\n",
1940 tmp);
1941 ctxt->wellFormed = 0;
1942 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00001943 }
1944 if ((ctxt->inSubset == 1) && (tmp == '%')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00001945 ctxt->errNo = XML_ERR_ENTITY_PE_INTERNAL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001946 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1947 ctxt->sax->error(ctxt->userData,
1948 "EntityValue: PEReferences forbidden in internal subset\n",
1949 tmp);
1950 ctxt->wellFormed = 0;
1951 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00001952 }
1953 if (name != NULL)
1954 xmlFree(name);
1955 }
1956 cur++;
1957 }
1958
1959 /*
Daniel Veillard10a2c651999-12-12 13:03:50 +00001960 * Then PEReference entities are substituted.
1961 */
1962 if (c != stop) {
1963 ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1964 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1965 ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
1966 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00001967 ctxt->disableSAX = 1;
1968 xmlFree(buf);
Daniel Veillard10a2c651999-12-12 13:03:50 +00001969 } else {
1970 NEXT;
1971 /*
1972 * NOTE: 4.4.7 Bypassed
1973 * When a general entity reference appears in the EntityValue in
1974 * an entity declaration, it is bypassed and left as is.
Daniel Veillardcf461992000-03-14 18:30:20 +00001975 * so XML_SUBSTITUTE_REF is not set here.
Daniel Veillard10a2c651999-12-12 13:03:50 +00001976 */
1977 ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
1978 0, 0, 0);
1979 if (orig != NULL)
1980 *orig = buf;
1981 else
1982 xmlFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001983 }
1984
1985 return(ret);
1986}
1987
Daniel Veillard11e00581998-10-24 18:27:49 +00001988/**
1989 * xmlParseAttValue:
1990 * @ctxt: an XML parser context
1991 *
1992 * parse a value for an attribute
Daniel Veillard011b63c1999-06-02 17:44:04 +00001993 * Note: the parser won't do substitution of entities here, this
Daniel Veillardb96e6431999-08-29 21:02:19 +00001994 * will be handled later in xmlStringGetNodeList
Daniel Veillard260a68f1998-08-13 03:39:55 +00001995 *
1996 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
1997 * "'" ([^<&'] | Reference)* "'"
Daniel Veillard1e346af1999-02-22 10:33:01 +00001998 *
Daniel Veillard7f858501999-11-17 17:32:38 +00001999 * 3.3.3 Attribute-Value Normalization:
2000 * Before the value of an attribute is passed to the application or
2001 * checked for validity, the XML processor must normalize it as follows:
2002 * - a character reference is processed by appending the referenced
2003 * character to the attribute value
2004 * - an entity reference is processed by recursively processing the
2005 * replacement text of the entity
2006 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
2007 * appending #x20 to the normalized value, except that only a single
2008 * #x20 is appended for a "#xD#xA" sequence that is part of an external
2009 * parsed entity or the literal entity value of an internal parsed entity
2010 * - other characters are processed by appending them to the normalized value
Daniel Veillard07136651999-11-18 14:02:05 +00002011 * If the declared value is not CDATA, then the XML processor must further
2012 * process the normalized attribute value by discarding any leading and
2013 * trailing space (#x20) characters, and by replacing sequences of space
2014 * (#x20) characters by a single space (#x20) character.
2015 * All attributes for which no declaration has been read should be treated
2016 * by a non-validating parser as if declared CDATA.
Daniel Veillard7f858501999-11-17 17:32:38 +00002017 *
2018 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002019 */
2020
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002021xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002022xmlParseAttValue(xmlParserCtxtPtr ctxt) {
Daniel Veillard7f858501999-11-17 17:32:38 +00002023 xmlChar limit = 0;
Daniel Veillardbe803962000-06-28 23:40:59 +00002024 xmlChar *buf = NULL;
2025 int len = 0;
2026 int buf_size = 0;
2027 int c, l;
Daniel Veillard7f858501999-11-17 17:32:38 +00002028 xmlChar *current = NULL;
2029 xmlEntityPtr ent;
Daniel Veillard7f858501999-11-17 17:32:38 +00002030
Daniel Veillard260a68f1998-08-13 03:39:55 +00002031
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002032 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00002033 if (NXT(0) == '"') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002034 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
Daniel Veillard7f858501999-11-17 17:32:38 +00002035 limit = '"';
Daniel Veillard260a68f1998-08-13 03:39:55 +00002036 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00002037 } else if (NXT(0) == '\'') {
Daniel Veillard7f858501999-11-17 17:32:38 +00002038 limit = '\'';
Daniel Veillardb05deb71999-08-10 19:04:08 +00002039 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002040 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002041 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002042 ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002043 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002044 ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002045 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002046 ctxt->disableSAX = 1;
Daniel Veillard7f858501999-11-17 17:32:38 +00002047 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002048 }
2049
Daniel Veillard7f858501999-11-17 17:32:38 +00002050 /*
2051 * allocate a translation buffer.
2052 */
Daniel Veillardbe803962000-06-28 23:40:59 +00002053 buf_size = XML_PARSER_BUFFER_SIZE;
2054 buf = (xmlChar *) xmlMalloc(buf_size * sizeof(xmlChar));
2055 if (buf == NULL) {
Daniel Veillard7f858501999-11-17 17:32:38 +00002056 perror("xmlParseAttValue: malloc failed");
2057 return(NULL);
2058 }
Daniel Veillard7f858501999-11-17 17:32:38 +00002059
2060 /*
2061 * Ok loop until we reach one of the ending char or a size limit.
2062 */
Daniel Veillardbe803962000-06-28 23:40:59 +00002063 c = CUR_CHAR(l);
Daniel Veillard4948eb42000-08-29 09:41:15 +00002064 while (((NXT(0) != limit) && /* checked */
2065 (c != '<')) || (ctxt->token != 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +00002066 if (c == 0) break;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002067 if (ctxt->token == '&') {
Daniel Veillardb1059e22000-09-16 14:02:43 +00002068 /*
2069 * The reparsing will be done in xmlStringGetNodeList()
2070 * called by the attribute() function in SAX.c
2071 */
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002072 static xmlChar buffer[6] = "&#38;";
2073
2074 if (len > buf_size - 10) {
2075 growBuffer(buf);
2076 }
2077 current = &buffer[0];
Daniel Veillard4948eb42000-08-29 09:41:15 +00002078 while (*current != 0) { /* non input consuming */
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002079 buf[len++] = *current++;
2080 }
2081 ctxt->token = 0;
2082 } else if ((c == '&') && (NXT(1) == '#')) {
Daniel Veillard7f858501999-11-17 17:32:38 +00002083 int val = xmlParseCharRef(ctxt);
Daniel Veillardb1059e22000-09-16 14:02:43 +00002084 if (val == '&') {
2085 /*
2086 * The reparsing will be done in xmlStringGetNodeList()
2087 * called by the attribute() function in SAX.c
2088 */
2089 static xmlChar buffer[6] = "&#38;";
2090
2091 if (len > buf_size - 10) {
2092 growBuffer(buf);
2093 }
2094 current = &buffer[0];
2095 while (*current != 0) { /* non input consuming */
2096 buf[len++] = *current++;
2097 }
2098 } else {
Daniel Veillard1e851392000-10-15 10:02:56 +00002099 len += xmlCopyChar(0, &buf[len], val);
Daniel Veillardb1059e22000-09-16 14:02:43 +00002100 }
Daniel Veillardbe803962000-06-28 23:40:59 +00002101 } else if (c == '&') {
Daniel Veillard7f858501999-11-17 17:32:38 +00002102 ent = xmlParseEntityRef(ctxt);
2103 if ((ent != NULL) &&
2104 (ctxt->replaceEntities != 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002105 xmlChar *rep;
Daniel Veillard7f858501999-11-17 17:32:38 +00002106
Daniel Veillardcf461992000-03-14 18:30:20 +00002107 if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
2108 rep = xmlStringDecodeEntities(ctxt, ent->content,
2109 XML_SUBSTITUTE_REF, 0, 0, 0);
2110 if (rep != NULL) {
2111 current = rep;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002112 while (*current != 0) { /* non input consuming */
Daniel Veillardbe803962000-06-28 23:40:59 +00002113 buf[len++] = *current++;
2114 if (len > buf_size - 10) {
2115 growBuffer(buf);
Daniel Veillardcf461992000-03-14 18:30:20 +00002116 }
2117 }
2118 xmlFree(rep);
Daniel Veillard7f858501999-11-17 17:32:38 +00002119 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002120 } else {
2121 if (ent->content != NULL)
Daniel Veillardbe803962000-06-28 23:40:59 +00002122 buf[len++] = ent->content[0];
Daniel Veillard7f858501999-11-17 17:32:38 +00002123 }
2124 } else if (ent != NULL) {
2125 int i = xmlStrlen(ent->name);
2126 const xmlChar *cur = ent->name;
2127
Daniel Veillardcf461992000-03-14 18:30:20 +00002128 /*
2129 * This may look absurd but is needed to detect
2130 * entities problems
2131 */
Daniel Veillard87b95392000-08-12 21:12:04 +00002132 if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
2133 (ent->content != NULL)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002134 xmlChar *rep;
2135 rep = xmlStringDecodeEntities(ctxt, ent->content,
2136 XML_SUBSTITUTE_REF, 0, 0, 0);
2137 if (rep != NULL)
2138 xmlFree(rep);
2139 }
2140
2141 /*
2142 * Just output the reference
2143 */
Daniel Veillardbe803962000-06-28 23:40:59 +00002144 buf[len++] = '&';
2145 if (len > buf_size - i - 10) {
2146 growBuffer(buf);
Daniel Veillard7f858501999-11-17 17:32:38 +00002147 }
2148 for (;i > 0;i--)
Daniel Veillardbe803962000-06-28 23:40:59 +00002149 buf[len++] = *cur++;
2150 buf[len++] = ';';
Daniel Veillard7f858501999-11-17 17:32:38 +00002151 }
Daniel Veillard7f858501999-11-17 17:32:38 +00002152 } else {
Daniel Veillardbe803962000-06-28 23:40:59 +00002153 if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
2154 COPY_BUF(l,buf,len,0x20);
2155 if (len > buf_size - 10) {
2156 growBuffer(buf);
Daniel Veillard7f858501999-11-17 17:32:38 +00002157 }
Daniel Veillard7f858501999-11-17 17:32:38 +00002158 } else {
Daniel Veillardbe803962000-06-28 23:40:59 +00002159 COPY_BUF(l,buf,len,c);
2160 if (len > buf_size - 10) {
2161 growBuffer(buf);
Daniel Veillard7f858501999-11-17 17:32:38 +00002162 }
Daniel Veillard7f858501999-11-17 17:32:38 +00002163 }
Daniel Veillardbe803962000-06-28 23:40:59 +00002164 NEXTL(l);
Daniel Veillard7f858501999-11-17 17:32:38 +00002165 }
Daniel Veillardbe803962000-06-28 23:40:59 +00002166 GROW;
2167 c = CUR_CHAR(l);
Daniel Veillard7f858501999-11-17 17:32:38 +00002168 }
Daniel Veillardbe803962000-06-28 23:40:59 +00002169 buf[len++] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002170 if (RAW == '<') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002171 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillard7f858501999-11-17 17:32:38 +00002172 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2173 ctxt->sax->error(ctxt->userData,
2174 "Unescaped '<' not allowed in attributes values\n");
Daniel Veillard7f858501999-11-17 17:32:38 +00002175 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002176 ctxt->disableSAX = 1;
2177 } else if (RAW != limit) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002178 ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
Daniel Veillard7f858501999-11-17 17:32:38 +00002179 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2180 ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
Daniel Veillard7f858501999-11-17 17:32:38 +00002181 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002182 ctxt->disableSAX = 1;
Daniel Veillard7f858501999-11-17 17:32:38 +00002183 } else
2184 NEXT;
Daniel Veillardbe803962000-06-28 23:40:59 +00002185 return(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002186}
2187
Daniel Veillard11e00581998-10-24 18:27:49 +00002188/**
2189 * xmlParseSystemLiteral:
2190 * @ctxt: an XML parser context
2191 *
2192 * parse an XML Literal
Daniel Veillard260a68f1998-08-13 03:39:55 +00002193 *
2194 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
Daniel Veillard1e346af1999-02-22 10:33:01 +00002195 *
2196 * Returns the SystemLiteral parsed or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002197 */
2198
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002199xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002200xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002201 xmlChar *buf = NULL;
2202 int len = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002203 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillardcf461992000-03-14 18:30:20 +00002204 int cur, l;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002205 xmlChar stop;
Daniel Veillardcf461992000-03-14 18:30:20 +00002206 int state = ctxt->instate;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002207 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002208
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002209 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00002210 if (RAW == '"') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002211 NEXT;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002212 stop = '"';
Daniel Veillardcf461992000-03-14 18:30:20 +00002213 } else if (RAW == '\'') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002214 NEXT;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002215 stop = '\'';
Daniel Veillard260a68f1998-08-13 03:39:55 +00002216 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002217 ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002218 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002219 ctxt->sax->error(ctxt->userData,
2220 "SystemLiteral \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002221 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002222 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002223 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002224 }
2225
Daniel Veillard10a2c651999-12-12 13:03:50 +00002226 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2227 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002228 xmlGenericError(xmlGenericErrorContext,
2229 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002230 return(NULL);
2231 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002232 ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
2233 cur = CUR_CHAR(l);
Daniel Veillard4948eb42000-08-29 09:41:15 +00002234 while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
Daniel Veillardcf461992000-03-14 18:30:20 +00002235 if (len + 5 >= size) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002236 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002237 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002238 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002239 xmlGenericError(xmlGenericErrorContext,
2240 "realloc of %d byte failed\n", size);
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002241 ctxt->instate = (xmlParserInputState) state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002242 return(NULL);
2243 }
2244 }
Daniel Veillard4948eb42000-08-29 09:41:15 +00002245 count++;
2246 if (count > 50) {
2247 GROW;
2248 count = 0;
2249 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002250 COPY_BUF(l,buf,len,cur);
2251 NEXTL(l);
2252 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002253 if (cur == 0) {
2254 GROW;
2255 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00002256 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002257 }
2258 }
2259 buf[len] = 0;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002260 ctxt->instate = (xmlParserInputState) state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002261 if (!IS_CHAR(cur)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002262 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002263 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2264 ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00002265 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002266 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002267 } else {
2268 NEXT;
2269 }
2270 return(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002271}
2272
Daniel Veillard11e00581998-10-24 18:27:49 +00002273/**
2274 * xmlParsePubidLiteral:
2275 * @ctxt: an XML parser context
Daniel Veillard260a68f1998-08-13 03:39:55 +00002276 *
Daniel Veillard11e00581998-10-24 18:27:49 +00002277 * parse an XML public literal
Daniel Veillard1e346af1999-02-22 10:33:01 +00002278 *
2279 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2280 *
2281 * Returns the PubidLiteral parsed or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002282 */
2283
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002284xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002285xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002286 xmlChar *buf = NULL;
2287 int len = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002288 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002289 xmlChar cur;
2290 xmlChar stop;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002291 int count = 0;
Daniel Veillard6077d031999-10-09 09:11:45 +00002292
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002293 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00002294 if (RAW == '"') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002295 NEXT;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002296 stop = '"';
Daniel Veillardcf461992000-03-14 18:30:20 +00002297 } else if (RAW == '\'') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002298 NEXT;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002299 stop = '\'';
Daniel Veillard260a68f1998-08-13 03:39:55 +00002300 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002301 ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002302 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002303 ctxt->sax->error(ctxt->userData,
2304 "SystemLiteral \" or ' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002305 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002306 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002307 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002308 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002309 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2310 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002311 xmlGenericError(xmlGenericErrorContext,
2312 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002313 return(NULL);
2314 }
2315 cur = CUR;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002316 while ((IS_PUBIDCHAR(cur)) && (cur != stop)) { /* checked */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002317 if (len + 1 >= size) {
2318 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002319 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002320 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002321 xmlGenericError(xmlGenericErrorContext,
2322 "realloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002323 return(NULL);
2324 }
2325 }
2326 buf[len++] = cur;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002327 count++;
2328 if (count > 50) {
2329 GROW;
2330 count = 0;
2331 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002332 NEXT;
2333 cur = CUR;
2334 if (cur == 0) {
2335 GROW;
2336 SHRINK;
2337 cur = CUR;
2338 }
2339 }
2340 buf[len] = 0;
2341 if (cur != stop) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002342 ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002343 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2344 ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00002345 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002346 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002347 } else {
2348 NEXT;
2349 }
2350 return(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002351}
2352
Daniel Veillard11e00581998-10-24 18:27:49 +00002353/**
2354 * xmlParseCharData:
2355 * @ctxt: an XML parser context
2356 * @cdata: int indicating whether we are within a CDATA section
2357 *
2358 * parse a CharData section.
2359 * if we are within a CDATA section ']]>' marks an end of section.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002360 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002361 * The right angle bracket (>) may be represented using the string "&gt;",
2362 * and must, for compatibility, be escaped using "&gt;" or a character
2363 * reference when it appears in the string "]]>" in content, when that
2364 * string is not marking the end of a CDATA section.
2365 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002366 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2367 */
2368
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002369void
2370xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002371 xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002372 int nbchar = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002373 int cur, l;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002374 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002375
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002376 SHRINK;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002377 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00002378 cur = CUR_CHAR(l);
Daniel Veillard4948eb42000-08-29 09:41:15 +00002379 while (((cur != '<') || (ctxt->token == '<')) && /* checked */
Daniel Veillard5e873c42000-04-12 13:27:38 +00002380 ((cur != '&') || (ctxt->token == '&')) &&
Daniel Veillardb1059e22000-09-16 14:02:43 +00002381 (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
Daniel Veillardb05deb71999-08-10 19:04:08 +00002382 if ((cur == ']') && (NXT(1) == ']') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002383 (NXT(2) == '>')) {
2384 if (cdata) break;
2385 else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002386 ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002387 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardcf461992000-03-14 18:30:20 +00002388 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002389 "Sequence ']]>' not allowed in content\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002390 /* Should this be relaxed ??? I see a "must here */
2391 ctxt->wellFormed = 0;
2392 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002393 }
2394 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002395 COPY_BUF(l,buf,nbchar,cur);
2396 if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002397 /*
2398 * Ok the segment is to be consumed as chars.
2399 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002400 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002401 if (areBlanks(ctxt, buf, nbchar)) {
2402 if (ctxt->sax->ignorableWhitespace != NULL)
2403 ctxt->sax->ignorableWhitespace(ctxt->userData,
2404 buf, nbchar);
2405 } else {
2406 if (ctxt->sax->characters != NULL)
2407 ctxt->sax->characters(ctxt->userData, buf, nbchar);
2408 }
2409 }
2410 nbchar = 0;
2411 }
Daniel Veillard4948eb42000-08-29 09:41:15 +00002412 count++;
2413 if (count > 50) {
2414 GROW;
2415 count = 0;
2416 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002417 NEXTL(l);
2418 cur = CUR_CHAR(l);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002419 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002420 if (nbchar != 0) {
2421 /*
2422 * Ok the segment is to be consumed as chars.
2423 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002424 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002425 if (areBlanks(ctxt, buf, nbchar)) {
2426 if (ctxt->sax->ignorableWhitespace != NULL)
2427 ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2428 } else {
2429 if (ctxt->sax->characters != NULL)
2430 ctxt->sax->characters(ctxt->userData, buf, nbchar);
2431 }
2432 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002433 }
2434}
2435
Daniel Veillard11e00581998-10-24 18:27:49 +00002436/**
2437 * xmlParseExternalID:
2438 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002439 * @publicID: a xmlChar** receiving PubidLiteral
Daniel Veillard1e346af1999-02-22 10:33:01 +00002440 * @strict: indicate whether we should restrict parsing to only
2441 * production [75], see NOTE below
Daniel Veillard11e00581998-10-24 18:27:49 +00002442 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002443 * Parse an External ID or a Public ID
2444 *
2445 * NOTE: Productions [75] and [83] interract badly since [75] can generate
2446 * 'PUBLIC' S PubidLiteral S SystemLiteral
Daniel Veillard260a68f1998-08-13 03:39:55 +00002447 *
2448 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2449 * | 'PUBLIC' S PubidLiteral S SystemLiteral
Daniel Veillard1e346af1999-02-22 10:33:01 +00002450 *
2451 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2452 *
2453 * Returns the function returns SystemLiteral and in the second
2454 * case publicID receives PubidLiteral, is strict is off
2455 * it is possible to return NULL and have publicID set.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002456 */
2457
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002458xmlChar *
2459xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2460 xmlChar *URI = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002461
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002462 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00002463 if ((RAW == 'S') && (NXT(1) == 'Y') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00002464 (NXT(2) == 'S') && (NXT(3) == 'T') &&
2465 (NXT(4) == 'E') && (NXT(5) == 'M')) {
2466 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002467 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002468 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002469 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002470 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002471 "Space required after 'SYSTEM'\n");
2472 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002473 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002474 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002475 SKIP_BLANKS;
2476 URI = xmlParseSystemLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002477 if (URI == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002478 ctxt->errNo = XML_ERR_URI_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002479 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002480 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002481 "xmlParseExternalID: SYSTEM, no URI\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002482 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002483 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002484 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002485 } else if ((RAW == 'P') && (NXT(1) == 'U') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00002486 (NXT(2) == 'B') && (NXT(3) == 'L') &&
2487 (NXT(4) == 'I') && (NXT(5) == 'C')) {
2488 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002489 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002490 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002491 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002492 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002493 "Space required after 'PUBLIC'\n");
2494 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002495 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002496 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002497 SKIP_BLANKS;
2498 *publicID = xmlParsePubidLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002499 if (*publicID == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002500 ctxt->errNo = XML_ERR_PUBID_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002501 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002502 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002503 "xmlParseExternalID: PUBLIC, no Public Identifier\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002504 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002505 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002506 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002507 if (strict) {
2508 /*
2509 * We don't handle [83] so "S SystemLiteral" is required.
2510 */
2511 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002512 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002513 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002514 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00002515 "Space required after the Public Identifier\n");
2516 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002517 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002518 }
2519 } else {
2520 /*
2521 * We handle [83] so we return immediately, if
2522 * "S SystemLiteral" is not detected. From a purely parsing
2523 * point of view that's a nice mess.
2524 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002525 const xmlChar *ptr;
2526 GROW;
2527
2528 ptr = CUR_PTR;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002529 if (!IS_BLANK(*ptr)) return(NULL);
2530
Daniel Veillard4948eb42000-08-29 09:41:15 +00002531 while (IS_BLANK(*ptr)) ptr++; /* TODO: dangerous, fix ! */
Daniel Veillardcf461992000-03-14 18:30:20 +00002532 if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002533 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002534 SKIP_BLANKS;
2535 URI = xmlParseSystemLiteral(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002536 if (URI == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002537 ctxt->errNo = XML_ERR_URI_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002538 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002539 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002540 "xmlParseExternalID: PUBLIC, no URI\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002541 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002542 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002543 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002544 }
2545 return(URI);
2546}
2547
Daniel Veillard11e00581998-10-24 18:27:49 +00002548/**
2549 * xmlParseComment:
Daniel Veillard1e346af1999-02-22 10:33:01 +00002550 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00002551 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002552 * Skip an XML (SGML) comment <!-- .... -->
Daniel Veillard260a68f1998-08-13 03:39:55 +00002553 * The spec says that "For compatibility, the string "--" (double-hyphen)
2554 * must not occur within comments. "
2555 *
2556 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
2557 */
Daniel Veillard517752b1999-04-05 12:20:10 +00002558void
Daniel Veillardb96e6431999-08-29 21:02:19 +00002559xmlParseComment(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002560 xmlChar *buf = NULL;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00002561 int len;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002562 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillardcf461992000-03-14 18:30:20 +00002563 int q, ql;
2564 int r, rl;
2565 int cur, l;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002566 xmlParserInputState state;
Daniel Veillardcf461992000-03-14 18:30:20 +00002567 xmlParserInputPtr input = ctxt->input;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002568 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002569
2570 /*
2571 * Check that there is a comment right here.
2572 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002573 if ((RAW != '<') || (NXT(1) != '!') ||
Daniel Veillard517752b1999-04-05 12:20:10 +00002574 (NXT(2) != '-') || (NXT(3) != '-')) return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002575
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002576 state = ctxt->instate;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002577 ctxt->instate = XML_PARSER_COMMENT;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002578 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002579 SKIP(4);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002580 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2581 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002582 xmlGenericError(xmlGenericErrorContext,
2583 "malloc of %d byte failed\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002584 ctxt->instate = state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002585 return;
2586 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002587 q = CUR_CHAR(ql);
2588 NEXTL(ql);
2589 r = CUR_CHAR(rl);
2590 NEXTL(rl);
2591 cur = CUR_CHAR(l);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00002592 len = 0;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002593 while (IS_CHAR(cur) && /* checked */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002594 ((cur != '>') ||
2595 (r != '-') || (q != '-'))) {
Daniel Veillard496a1cf2000-05-03 14:20:55 +00002596 if ((r == '-') && (q == '-') && (len > 1)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002597 ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002598 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002599 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00002600 "Comment must not contain '--' (double-hyphen)`\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002601 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002602 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002603 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002604 if (len + 5 >= size) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002605 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002606 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002607 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002608 xmlGenericError(xmlGenericErrorContext,
2609 "realloc of %d byte failed\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002610 ctxt->instate = state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002611 return;
2612 }
2613 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002614 COPY_BUF(ql,buf,len,q);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002615 q = r;
Daniel Veillardcf461992000-03-14 18:30:20 +00002616 ql = rl;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002617 r = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00002618 rl = l;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002619
2620 count++;
2621 if (count > 50) {
2622 GROW;
2623 count = 0;
2624 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002625 NEXTL(l);
2626 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002627 if (cur == 0) {
2628 SHRINK;
2629 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00002630 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002631 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002632 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002633 buf[len] = 0;
2634 if (!IS_CHAR(cur)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002635 ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002636 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002637 ctxt->sax->error(ctxt->userData,
Daniel Veillard10a2c651999-12-12 13:03:50 +00002638 "Comment not terminated \n<!--%.50s\n", buf);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002639 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002640 ctxt->disableSAX = 1;
2641 xmlFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002642 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00002643 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002644 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00002645 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2646 ctxt->sax->error(ctxt->userData,
2647"Comment doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002648 ctxt->wellFormed = 0;
2649 ctxt->disableSAX = 1;
2650 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002651 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00002652 if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
2653 (!ctxt->disableSAX))
Daniel Veillard10a2c651999-12-12 13:03:50 +00002654 ctxt->sax->comment(ctxt->userData, buf);
2655 xmlFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002656 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002657 ctxt->instate = state;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002658}
2659
Daniel Veillard11e00581998-10-24 18:27:49 +00002660/**
2661 * xmlParsePITarget:
2662 * @ctxt: an XML parser context
2663 *
2664 * parse the name of a PI
Daniel Veillard260a68f1998-08-13 03:39:55 +00002665 *
2666 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
Daniel Veillard1e346af1999-02-22 10:33:01 +00002667 *
2668 * Returns the PITarget name or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00002669 */
2670
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002671xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002672xmlParsePITarget(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002673 xmlChar *name;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002674
2675 name = xmlParseName(ctxt);
Daniel Veillard3c558c31999-12-22 11:30:41 +00002676 if ((name != NULL) &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00002677 ((name[0] == 'x') || (name[0] == 'X')) &&
2678 ((name[1] == 'm') || (name[1] == 'M')) &&
2679 ((name[2] == 'l') || (name[2] == 'L'))) {
Daniel Veillard3c558c31999-12-22 11:30:41 +00002680 int i;
Daniel Veillardcf461992000-03-14 18:30:20 +00002681 if ((name[0] == 'x') && (name[1] == 'm') &&
2682 (name[2] == 'l') && (name[3] == 0)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002683 ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
Daniel Veillardcf461992000-03-14 18:30:20 +00002684 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2685 ctxt->sax->error(ctxt->userData,
2686 "XML declaration allowed only at the start of the document\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002687 ctxt->wellFormed = 0;
2688 ctxt->disableSAX = 1;
2689 return(name);
2690 } else if (name[3] == 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002691 ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
Daniel Veillardcf461992000-03-14 18:30:20 +00002692 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2693 ctxt->sax->error(ctxt->userData, "Invalid PI name\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002694 ctxt->wellFormed = 0;
2695 ctxt->disableSAX = 1;
2696 return(name);
2697 }
Daniel Veillard3c558c31999-12-22 11:30:41 +00002698 for (i = 0;;i++) {
2699 if (xmlW3CPIs[i] == NULL) break;
Daniel Veillard8b5dd832000-10-01 20:28:44 +00002700 if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
Daniel Veillard3c558c31999-12-22 11:30:41 +00002701 return(name);
2702 }
2703 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002704 ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
Daniel Veillard3c558c31999-12-22 11:30:41 +00002705 ctxt->sax->warning(ctxt->userData,
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002706 "xmlParsePItarget: invalid name prefix 'xml'\n");
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002707 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002708 }
2709 return(name);
2710}
2711
Daniel Veillard11e00581998-10-24 18:27:49 +00002712/**
2713 * xmlParsePI:
2714 * @ctxt: an XML parser context
2715 *
2716 * parse an XML Processing Instruction.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002717 *
2718 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
Daniel Veillard1e346af1999-02-22 10:33:01 +00002719 *
2720 * The processing is transfered to SAX once parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002721 */
2722
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002723void
2724xmlParsePI(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002725 xmlChar *buf = NULL;
2726 int len = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002727 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillardcf461992000-03-14 18:30:20 +00002728 int cur, l;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002729 xmlChar *target;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002730 xmlParserInputState state;
Daniel Veillard4948eb42000-08-29 09:41:15 +00002731 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002732
Daniel Veillardcf461992000-03-14 18:30:20 +00002733 if ((RAW == '<') && (NXT(1) == '?')) {
2734 xmlParserInputPtr input = ctxt->input;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002735 state = ctxt->instate;
2736 ctxt->instate = XML_PARSER_PI;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002737 /*
2738 * this is a Processing Instruction.
2739 */
2740 SKIP(2);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002741 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002742
2743 /*
2744 * Parse the target name and check for special support like
2745 * namespace.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002746 */
2747 target = xmlParsePITarget(ctxt);
2748 if (target != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002749 if ((RAW == '?') && (NXT(1) == '>')) {
2750 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002751 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00002752 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2753 ctxt->sax->error(ctxt->userData,
2754 "PI declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002755 ctxt->wellFormed = 0;
2756 ctxt->disableSAX = 1;
2757 }
2758 SKIP(2);
2759
2760 /*
2761 * SAX: PI detected.
2762 */
2763 if ((ctxt->sax) && (!ctxt->disableSAX) &&
2764 (ctxt->sax->processingInstruction != NULL))
2765 ctxt->sax->processingInstruction(ctxt->userData,
2766 target, NULL);
2767 ctxt->instate = state;
2768 xmlFree(target);
2769 return;
2770 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002771 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
2772 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002773 xmlGenericError(xmlGenericErrorContext,
2774 "malloc of %d byte failed\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002775 ctxt->instate = state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002776 return;
2777 }
2778 cur = CUR;
2779 if (!IS_BLANK(cur)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002780 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002781 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2782 ctxt->sax->error(ctxt->userData,
2783 "xmlParsePI: PI %s space expected\n", target);
2784 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002785 ctxt->disableSAX = 1;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002786 }
2787 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00002788 cur = CUR_CHAR(l);
Daniel Veillard4948eb42000-08-29 09:41:15 +00002789 while (IS_CHAR(cur) && /* checked */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002790 ((cur != '?') || (NXT(1) != '>'))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002791 if (len + 5 >= size) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002792 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00002793 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002794 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00002795 xmlGenericError(xmlGenericErrorContext,
2796 "realloc of %d byte failed\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002797 ctxt->instate = state;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002798 return;
2799 }
2800 }
Daniel Veillard4948eb42000-08-29 09:41:15 +00002801 count++;
2802 if (count > 50) {
2803 GROW;
2804 count = 0;
2805 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002806 COPY_BUF(l,buf,len,cur);
2807 NEXTL(l);
2808 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002809 if (cur == 0) {
2810 SHRINK;
2811 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00002812 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00002813 }
2814 }
2815 buf[len] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002816 if (cur != '?') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002817 ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
Daniel Veillard517752b1999-04-05 12:20:10 +00002818 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002819 ctxt->sax->error(ctxt->userData,
Daniel Veillard517752b1999-04-05 12:20:10 +00002820 "xmlParsePI: PI %s never end ...\n", target);
2821 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002822 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002823 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00002824 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002825 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00002826 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2827 ctxt->sax->error(ctxt->userData,
2828 "PI declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002829 ctxt->wellFormed = 0;
2830 ctxt->disableSAX = 1;
2831 }
Daniel Veillard517752b1999-04-05 12:20:10 +00002832 SKIP(2);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002833
Daniel Veillard517752b1999-04-05 12:20:10 +00002834 /*
2835 * SAX: PI detected.
2836 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002837 if ((ctxt->sax) && (!ctxt->disableSAX) &&
Daniel Veillard517752b1999-04-05 12:20:10 +00002838 (ctxt->sax->processingInstruction != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00002839 ctxt->sax->processingInstruction(ctxt->userData,
Daniel Veillard10a2c651999-12-12 13:03:50 +00002840 target, buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002841 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002842 xmlFree(buf);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002843 xmlFree(target);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002844 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002845 ctxt->errNo = XML_ERR_PI_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002846 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00002847 ctxt->sax->error(ctxt->userData,
2848 "xmlParsePI : no target name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002849 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002850 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002851 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002852 ctxt->instate = state;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002853 }
2854}
2855
Daniel Veillard11e00581998-10-24 18:27:49 +00002856/**
2857 * xmlParseNotationDecl:
2858 * @ctxt: an XML parser context
2859 *
2860 * parse a notation declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861 *
2862 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
2863 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 * Hence there is actually 3 choices:
2865 * 'PUBLIC' S PubidLiteral
2866 * 'PUBLIC' S PubidLiteral S SystemLiteral
2867 * and 'SYSTEM' S SystemLiteral
Daniel Veillard11e00581998-10-24 18:27:49 +00002868 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002869 * See the NOTE on xmlParseExternalID().
Daniel Veillard260a68f1998-08-13 03:39:55 +00002870 */
2871
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002872void
2873xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002874 xmlChar *name;
2875 xmlChar *Pubid;
2876 xmlChar *Systemid;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002877
Daniel Veillardcf461992000-03-14 18:30:20 +00002878 if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00002879 (NXT(2) == 'N') && (NXT(3) == 'O') &&
2880 (NXT(4) == 'T') && (NXT(5) == 'A') &&
2881 (NXT(6) == 'T') && (NXT(7) == 'I') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00002882 (NXT(8) == 'O') && (NXT(9) == 'N')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002883 xmlParserInputPtr input = ctxt->input;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002884 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002885 SKIP(10);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002886 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002887 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00002888 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002889 ctxt->sax->error(ctxt->userData,
2890 "Space required after '<!NOTATION'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002891 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002892 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002893 return;
2894 }
2895 SKIP_BLANKS;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002896
2897 name = xmlParseName(ctxt);
2898 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002899 ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002900 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002901 ctxt->sax->error(ctxt->userData,
2902 "NOTATION: Name expected here\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00002903 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002904 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002905 return;
2906 }
2907 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002908 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002909 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002910 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00002911 "Space required after the NOTATION name'\n");
2912 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002913 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002914 return;
2915 }
2916 SKIP_BLANKS;
2917
Daniel Veillard260a68f1998-08-13 03:39:55 +00002918 /*
Daniel Veillard1e346af1999-02-22 10:33:01 +00002919 * Parse the IDs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002920 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002921 Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002922 SKIP_BLANKS;
2923
Daniel Veillardcf461992000-03-14 18:30:20 +00002924 if (RAW == '>') {
2925 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002926 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00002927 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2928 ctxt->sax->error(ctxt->userData,
2929"Notation declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00002930 ctxt->wellFormed = 0;
2931 ctxt->disableSAX = 1;
2932 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002933 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00002934 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
2935 (ctxt->sax->notationDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002936 ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002937 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002938 ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002939 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00002940 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00002941 "'>' required to close NOTATION declaration\n");
2942 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002943 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002944 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002945 xmlFree(name);
2946 if (Systemid != NULL) xmlFree(Systemid);
2947 if (Pubid != NULL) xmlFree(Pubid);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002948 }
2949}
2950
Daniel Veillard11e00581998-10-24 18:27:49 +00002951/**
2952 * xmlParseEntityDecl:
2953 * @ctxt: an XML parser context
2954 *
2955 * parse <!ENTITY declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00002956 *
2957 * [70] EntityDecl ::= GEDecl | PEDecl
2958 *
2959 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
2960 *
2961 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
2962 *
2963 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
2964 *
2965 * [74] PEDef ::= EntityValue | ExternalID
2966 *
2967 * [76] NDataDecl ::= S 'NDATA' S Name
Daniel Veillardb05deb71999-08-10 19:04:08 +00002968 *
2969 * [ VC: Notation Declared ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00002970 * The Name must match the declared name of a notation.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002971 */
2972
Daniel Veillard0ba4d531998-11-01 19:34:31 +00002973void
2974xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002975 xmlChar *name = NULL;
2976 xmlChar *value = NULL;
2977 xmlChar *URI = NULL, *literal = NULL;
2978 xmlChar *ndata = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002979 int isParameter = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002980 xmlChar *orig = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002981
Daniel Veillardb05deb71999-08-10 19:04:08 +00002982 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00002983 if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00002984 (NXT(2) == 'E') && (NXT(3) == 'N') &&
2985 (NXT(4) == 'T') && (NXT(5) == 'I') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002986 (NXT(6) == 'T') && (NXT(7) == 'Y')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002987 xmlParserInputPtr input = ctxt->input;
Daniel Veillardb05deb71999-08-10 19:04:08 +00002988 ctxt->instate = XML_PARSER_ENTITY_DECL;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002989 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002990 SKIP(8);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002991 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00002992 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002993 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00002994 ctxt->sax->error(ctxt->userData,
2995 "Space required after '<!ENTITY'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002996 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00002997 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002998 }
2999 SKIP_BLANKS;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003000
Daniel Veillardcf461992000-03-14 18:30:20 +00003001 if (RAW == '%') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003002 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003003 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003004 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003005 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003006 ctxt->sax->error(ctxt->userData,
3007 "Space required after '%'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003008 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003009 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003010 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003011 SKIP_BLANKS;
3012 isParameter = 1;
3013 }
3014
3015 name = xmlParseName(ctxt);
3016 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003017 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003018 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003019 ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003020 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003021 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003022 return;
3023 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003024 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003025 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003026 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003027 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003028 "Space required after the entity name\n");
3029 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003030 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003031 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003032 SKIP_BLANKS;
3033
3034 /*
Daniel Veillard1e346af1999-02-22 10:33:01 +00003035 * handle the various case of definitions...
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 */
3037 if (isParameter) {
Daniel Veillard39c7d712000-09-10 16:14:55 +00003038 if ((RAW == '"') || (RAW == '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003039 value = xmlParseEntityValue(ctxt, &orig);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003040 if (value) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003041 if ((ctxt->sax != NULL) &&
3042 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003043 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003044 XML_INTERNAL_PARAMETER_ENTITY,
3045 NULL, NULL, value);
3046 }
Daniel Veillard39c7d712000-09-10 16:14:55 +00003047 } else {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003048 URI = xmlParseExternalID(ctxt, &literal, 1);
Daniel Veillardcf461992000-03-14 18:30:20 +00003049 if ((URI == NULL) && (literal == NULL)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003050 ctxt->errNo = XML_ERR_VALUE_REQUIRED;
Daniel Veillardcf461992000-03-14 18:30:20 +00003051 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3052 ctxt->sax->error(ctxt->userData,
3053 "Entity value required\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00003054 ctxt->wellFormed = 0;
3055 ctxt->disableSAX = 1;
3056 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003057 if (URI) {
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003058 xmlURIPtr uri;
3059
3060 uri = xmlParseURI((const char *) URI);
3061 if (uri == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003062 ctxt->errNo = XML_ERR_INVALID_URI;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003063 if ((ctxt->sax != NULL) &&
3064 (!ctxt->disableSAX) &&
3065 (ctxt->sax->error != NULL))
3066 ctxt->sax->error(ctxt->userData,
3067 "Invalid URI: %s\n", URI);
3068 ctxt->wellFormed = 0;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003069 } else {
3070 if (uri->fragment != NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003071 ctxt->errNo = XML_ERR_URI_FRAGMENT;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003072 if ((ctxt->sax != NULL) &&
3073 (!ctxt->disableSAX) &&
3074 (ctxt->sax->error != NULL))
3075 ctxt->sax->error(ctxt->userData,
3076 "Fragment not allowed: %s\n", URI);
3077 ctxt->wellFormed = 0;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003078 } else {
3079 if ((ctxt->sax != NULL) &&
3080 (!ctxt->disableSAX) &&
3081 (ctxt->sax->entityDecl != NULL))
3082 ctxt->sax->entityDecl(ctxt->userData, name,
3083 XML_EXTERNAL_PARAMETER_ENTITY,
3084 literal, URI, NULL);
3085 }
3086 xmlFreeURI(uri);
3087 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003088 }
3089 }
3090 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00003091 if ((RAW == '"') || (RAW == '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003092 value = xmlParseEntityValue(ctxt, &orig);
Daniel Veillardcf461992000-03-14 18:30:20 +00003093 if ((ctxt->sax != NULL) &&
3094 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003095 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003096 XML_INTERNAL_GENERAL_ENTITY,
3097 NULL, NULL, value);
3098 } else {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003099 URI = xmlParseExternalID(ctxt, &literal, 1);
Daniel Veillardcf461992000-03-14 18:30:20 +00003100 if ((URI == NULL) && (literal == NULL)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003101 ctxt->errNo = XML_ERR_VALUE_REQUIRED;
Daniel Veillardcf461992000-03-14 18:30:20 +00003102 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3103 ctxt->sax->error(ctxt->userData,
3104 "Entity value required\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00003105 ctxt->wellFormed = 0;
3106 ctxt->disableSAX = 1;
3107 }
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003108 if (URI) {
3109 xmlURIPtr uri;
3110
3111 uri = xmlParseURI((const char *)URI);
3112 if (uri == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003113 ctxt->errNo = XML_ERR_INVALID_URI;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003114 if ((ctxt->sax != NULL) &&
3115 (!ctxt->disableSAX) &&
3116 (ctxt->sax->error != NULL))
3117 ctxt->sax->error(ctxt->userData,
3118 "Invalid URI: %s\n", URI);
3119 ctxt->wellFormed = 0;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003120 } else {
3121 if (uri->fragment != NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003122 ctxt->errNo = XML_ERR_URI_FRAGMENT;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003123 if ((ctxt->sax != NULL) &&
3124 (!ctxt->disableSAX) &&
3125 (ctxt->sax->error != NULL))
3126 ctxt->sax->error(ctxt->userData,
3127 "Fragment not allowed: %s\n", URI);
3128 ctxt->wellFormed = 0;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003129 }
3130 xmlFreeURI(uri);
3131 }
3132 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003133 if ((RAW != '>') && (!IS_BLANK(CUR))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003134 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003135 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003136 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003137 "Space required before 'NDATA'\n");
3138 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003139 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003140 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003141 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00003142 if ((RAW == 'N') && (NXT(1) == 'D') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003143 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3144 (NXT(4) == 'A')) {
3145 SKIP(5);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003146 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003147 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003148 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003149 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003150 "Space required after 'NDATA'\n");
3151 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003152 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003153 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003154 SKIP_BLANKS;
3155 ndata = xmlParseName(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00003156 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
Daniel Veillardb96e6431999-08-29 21:02:19 +00003157 (ctxt->sax->unparsedEntityDecl != NULL))
3158 ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003159 literal, URI, ndata);
3160 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00003161 if ((ctxt->sax != NULL) &&
3162 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003163 ctxt->sax->entityDecl(ctxt->userData, name,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003164 XML_EXTERNAL_GENERAL_PARSED_ENTITY,
3165 literal, URI, NULL);
3166 }
3167 }
3168 }
3169 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00003170 if (RAW != '>') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003171 ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003172 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003173 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00003174 "xmlParseEntityDecl: entity %s not terminated\n", name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003175 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003176 ctxt->disableSAX = 1;
3177 } else {
3178 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003179 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00003180 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3181 ctxt->sax->error(ctxt->userData,
3182"Entity declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00003183 ctxt->wellFormed = 0;
3184 ctxt->disableSAX = 1;
3185 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003186 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00003187 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00003188 if (orig != NULL) {
3189 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00003190 * Ugly mechanism to save the raw entity value.
Daniel Veillard011b63c1999-06-02 17:44:04 +00003191 */
3192 xmlEntityPtr cur = NULL;
3193
Daniel Veillardb05deb71999-08-10 19:04:08 +00003194 if (isParameter) {
3195 if ((ctxt->sax != NULL) &&
3196 (ctxt->sax->getParameterEntity != NULL))
Daniel Veillardc08a2c61999-09-08 21:35:25 +00003197 cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003198 } else {
3199 if ((ctxt->sax != NULL) &&
3200 (ctxt->sax->getEntity != NULL))
Daniel Veillardc08a2c61999-09-08 21:35:25 +00003201 cur = ctxt->sax->getEntity(ctxt->userData, name);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003202 }
3203 if (cur != NULL) {
3204 if (cur->orig != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003205 xmlFree(orig);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003206 else
3207 cur->orig = orig;
3208 } else
Daniel Veillard6454aec1999-09-02 22:04:43 +00003209 xmlFree(orig);
Daniel Veillard011b63c1999-06-02 17:44:04 +00003210 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00003211 if (name != NULL) xmlFree(name);
3212 if (value != NULL) xmlFree(value);
3213 if (URI != NULL) xmlFree(URI);
3214 if (literal != NULL) xmlFree(literal);
3215 if (ndata != NULL) xmlFree(ndata);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003216 }
3217}
3218
Daniel Veillard11e00581998-10-24 18:27:49 +00003219/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003220 * xmlParseDefaultDecl:
3221 * @ctxt: an XML parser context
3222 * @value: Receive a possible fixed default value for the attribute
3223 *
3224 * Parse an attribute default declaration
3225 *
3226 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
3227 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003228 * [ VC: Required Attribute ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003229 * if the default declaration is the keyword #REQUIRED, then the
3230 * attribute must be specified for all elements of the type in the
3231 * attribute-list declaration.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003232 *
3233 * [ VC: Attribute Default Legal ]
3234 * The declared default value must meet the lexical constraints of
3235 * the declared attribute type c.f. xmlValidateAttributeDecl()
3236 *
3237 * [ VC: Fixed Attribute Default ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003238 * if an attribute has a default value declared with the #FIXED
3239 * keyword, instances of that attribute must match the default value.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003240 *
3241 * [ WFC: No < in Attribute Values ]
3242 * handled in xmlParseAttValue()
3243 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003244 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
3245 * or XML_ATTRIBUTE_FIXED.
3246 */
3247
3248int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003249xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003250 int val;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003251 xmlChar *ret;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003252
3253 *value = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00003254 if ((RAW == '#') && (NXT(1) == 'R') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003255 (NXT(2) == 'E') && (NXT(3) == 'Q') &&
3256 (NXT(4) == 'U') && (NXT(5) == 'I') &&
3257 (NXT(6) == 'R') && (NXT(7) == 'E') &&
3258 (NXT(8) == 'D')) {
3259 SKIP(9);
3260 return(XML_ATTRIBUTE_REQUIRED);
3261 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003262 if ((RAW == '#') && (NXT(1) == 'I') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003263 (NXT(2) == 'M') && (NXT(3) == 'P') &&
3264 (NXT(4) == 'L') && (NXT(5) == 'I') &&
3265 (NXT(6) == 'E') && (NXT(7) == 'D')) {
3266 SKIP(8);
3267 return(XML_ATTRIBUTE_IMPLIED);
3268 }
3269 val = XML_ATTRIBUTE_NONE;
Daniel Veillardcf461992000-03-14 18:30:20 +00003270 if ((RAW == '#') && (NXT(1) == 'F') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003271 (NXT(2) == 'I') && (NXT(3) == 'X') &&
3272 (NXT(4) == 'E') && (NXT(5) == 'D')) {
3273 SKIP(6);
3274 val = XML_ATTRIBUTE_FIXED;
3275 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003276 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003277 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003278 ctxt->sax->error(ctxt->userData,
3279 "Space required after '#FIXED'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003280 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003281 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003282 }
3283 SKIP_BLANKS;
3284 }
3285 ret = xmlParseAttValue(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003286 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003287 if (ret == NULL) {
3288 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003289 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003290 "Attribute default value declaration error\n");
3291 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003292 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003293 } else
3294 *value = ret;
3295 return(val);
3296}
3297
3298/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003299 * xmlParseNotationType:
3300 * @ctxt: an XML parser context
3301 *
3302 * parse an Notation attribute type.
3303 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003304 * Note: the leading 'NOTATION' S part has already being parsed...
3305 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003306 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3307 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003308 * [ VC: Notation Attributes ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003309 * Values of this type must match one of the notation names included
Daniel Veillardb05deb71999-08-10 19:04:08 +00003310 * in the declaration; all notation names in the declaration must be declared.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003311 *
3312 * Returns: the notation attribute tree built while parsing
3313 */
3314
3315xmlEnumerationPtr
3316xmlParseNotationType(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003317 xmlChar *name;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003318 xmlEnumerationPtr ret = NULL, last = NULL, cur;
3319
Daniel Veillardcf461992000-03-14 18:30:20 +00003320 if (RAW != '(') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003321 ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003322 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003323 ctxt->sax->error(ctxt->userData,
3324 "'(' required to start 'NOTATION'\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00003325 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003326 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003327 return(NULL);
3328 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003329 SHRINK;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003330 do {
3331 NEXT;
3332 SKIP_BLANKS;
3333 name = xmlParseName(ctxt);
3334 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003335 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003336 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003337 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003338 "Name expected in NOTATION declaration\n");
3339 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003340 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003341 return(ret);
3342 }
3343 cur = xmlCreateEnumeration(name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003344 xmlFree(name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003345 if (cur == NULL) return(ret);
3346 if (last == NULL) ret = last = cur;
3347 else {
3348 last->next = cur;
3349 last = cur;
3350 }
3351 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00003352 } while (RAW == '|');
3353 if (RAW != ')') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003354 ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003355 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003356 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003357 "')' required to finish NOTATION declaration\n");
3358 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003359 ctxt->disableSAX = 1;
3360 if ((last != NULL) && (last != ret))
3361 xmlFreeEnumeration(last);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003362 return(ret);
3363 }
3364 NEXT;
3365 return(ret);
3366}
3367
3368/**
3369 * xmlParseEnumerationType:
3370 * @ctxt: an XML parser context
3371 *
3372 * parse an Enumeration attribute type.
3373 *
3374 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
3375 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003376 * [ VC: Enumeration ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003377 * Values of this type must match one of the Nmtoken tokens in
Daniel Veillardb05deb71999-08-10 19:04:08 +00003378 * the declaration
3379 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003380 * Returns: the enumeration attribute tree built while parsing
3381 */
3382
3383xmlEnumerationPtr
3384xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003385 xmlChar *name;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003386 xmlEnumerationPtr ret = NULL, last = NULL, cur;
3387
Daniel Veillardcf461992000-03-14 18:30:20 +00003388 if (RAW != '(') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003389 ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003390 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003391 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003392 "'(' required to start ATTLIST enumeration\n");
3393 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003394 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003395 return(NULL);
3396 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003397 SHRINK;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003398 do {
3399 NEXT;
3400 SKIP_BLANKS;
3401 name = xmlParseNmtoken(ctxt);
3402 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003403 ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003404 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003405 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003406 "NmToken expected in ATTLIST enumeration\n");
3407 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003408 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003409 return(ret);
3410 }
3411 cur = xmlCreateEnumeration(name);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003412 xmlFree(name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003413 if (cur == NULL) return(ret);
3414 if (last == NULL) ret = last = cur;
3415 else {
3416 last->next = cur;
3417 last = cur;
3418 }
3419 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00003420 } while (RAW == '|');
3421 if (RAW != ')') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003422 ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003423 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003424 ctxt->sax->error(ctxt->userData,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003425 "')' required to finish ATTLIST enumeration\n");
3426 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003427 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003428 return(ret);
3429 }
3430 NEXT;
3431 return(ret);
3432}
3433
3434/**
Daniel Veillard11e00581998-10-24 18:27:49 +00003435 * xmlParseEnumeratedType:
3436 * @ctxt: an XML parser context
Daniel Veillard1e346af1999-02-22 10:33:01 +00003437 * @tree: the enumeration tree built while parsing
Daniel Veillard11e00581998-10-24 18:27:49 +00003438 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003439 * parse an Enumerated attribute type.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003440 *
3441 * [57] EnumeratedType ::= NotationType | Enumeration
3442 *
3443 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3444 *
Daniel Veillard11e00581998-10-24 18:27:49 +00003445 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003446 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
Daniel Veillard260a68f1998-08-13 03:39:55 +00003447 */
3448
Daniel Veillard1e346af1999-02-22 10:33:01 +00003449int
3450xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003451 if ((RAW == 'N') && (NXT(1) == 'O') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003452 (NXT(2) == 'T') && (NXT(3) == 'A') &&
3453 (NXT(4) == 'T') && (NXT(5) == 'I') &&
3454 (NXT(6) == 'O') && (NXT(7) == 'N')) {
3455 SKIP(8);
3456 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003457 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003458 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003459 ctxt->sax->error(ctxt->userData,
3460 "Space required after 'NOTATION'\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00003461 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003462 ctxt->disableSAX = 1;
Daniel Veillard1e346af1999-02-22 10:33:01 +00003463 return(0);
3464 }
3465 SKIP_BLANKS;
3466 *tree = xmlParseNotationType(ctxt);
3467 if (*tree == NULL) return(0);
3468 return(XML_ATTRIBUTE_NOTATION);
3469 }
3470 *tree = xmlParseEnumerationType(ctxt);
3471 if (*tree == NULL) return(0);
3472 return(XML_ATTRIBUTE_ENUMERATION);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003473}
3474
Daniel Veillard11e00581998-10-24 18:27:49 +00003475/**
3476 * xmlParseAttributeType:
3477 * @ctxt: an XML parser context
Daniel Veillard1e346af1999-02-22 10:33:01 +00003478 * @tree: the enumeration tree built while parsing
Daniel Veillard11e00581998-10-24 18:27:49 +00003479 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003480 * parse the Attribute list def for an element
Daniel Veillard260a68f1998-08-13 03:39:55 +00003481 *
3482 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
3483 *
3484 * [55] StringType ::= 'CDATA'
3485 *
3486 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
3487 * 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
Daniel Veillard11e00581998-10-24 18:27:49 +00003488 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003489 * Validity constraints for attribute values syntax are checked in
3490 * xmlValidateAttributeValue()
3491 *
3492 * [ VC: ID ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003493 * Values of type ID must match the Name production. A name must not
Daniel Veillardb05deb71999-08-10 19:04:08 +00003494 * appear more than once in an XML document as a value of this type;
3495 * i.e., ID values must uniquely identify the elements which bear them.
3496 *
3497 * [ VC: One ID per Element Type ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003498 * No element type may have more than one ID attribute specified.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003499 *
3500 * [ VC: ID Attribute Default ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003501 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003502 *
3503 * [ VC: IDREF ]
3504 * Values of type IDREF must match the Name production, and values
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003505 * of type IDREFS must match Names; each IDREF Name must match the value
Daniel Veillardb96e6431999-08-29 21:02:19 +00003506 * of an ID attribute on some element in the XML document; i.e. IDREF
Daniel Veillardb05deb71999-08-10 19:04:08 +00003507 * values must match the value of some ID attribute.
3508 *
3509 * [ VC: Entity Name ]
3510 * Values of type ENTITY must match the Name production, values
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003511 * of type ENTITIES must match Names; each Entity Name must match the
Daniel Veillardb96e6431999-08-29 21:02:19 +00003512 * name of an unparsed entity declared in the DTD.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003513 *
3514 * [ VC: Name Token ]
3515 * Values of type NMTOKEN must match the Nmtoken production; values
3516 * of type NMTOKENS must match Nmtokens.
3517 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003518 * Returns the attribute type
Daniel Veillard260a68f1998-08-13 03:39:55 +00003519 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003520int
Daniel Veillard1e346af1999-02-22 10:33:01 +00003521xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003522 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00003523 if ((RAW == 'C') && (NXT(1) == 'D') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003524 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3525 (NXT(4) == 'A')) {
3526 SKIP(5);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003527 return(XML_ATTRIBUTE_CDATA);
Daniel Veillardcf461992000-03-14 18:30:20 +00003528 } else if ((RAW == 'I') && (NXT(1) == 'D') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003529 (NXT(2) == 'R') && (NXT(3) == 'E') &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00003530 (NXT(4) == 'F') && (NXT(5) == 'S')) {
3531 SKIP(6);
3532 return(XML_ATTRIBUTE_IDREFS);
Daniel Veillardcf461992000-03-14 18:30:20 +00003533 } else if ((RAW == 'I') && (NXT(1) == 'D') &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00003534 (NXT(2) == 'R') && (NXT(3) == 'E') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003535 (NXT(4) == 'F')) {
3536 SKIP(5);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003537 return(XML_ATTRIBUTE_IDREF);
Daniel Veillardcf461992000-03-14 18:30:20 +00003538 } else if ((RAW == 'I') && (NXT(1) == 'D')) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003539 SKIP(2);
3540 return(XML_ATTRIBUTE_ID);
Daniel Veillardcf461992000-03-14 18:30:20 +00003541 } else if ((RAW == 'E') && (NXT(1) == 'N') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003542 (NXT(2) == 'T') && (NXT(3) == 'I') &&
3543 (NXT(4) == 'T') && (NXT(5) == 'Y')) {
3544 SKIP(6);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003545 return(XML_ATTRIBUTE_ENTITY);
Daniel Veillardcf461992000-03-14 18:30:20 +00003546 } else if ((RAW == 'E') && (NXT(1) == 'N') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003547 (NXT(2) == 'T') && (NXT(3) == 'I') &&
3548 (NXT(4) == 'T') && (NXT(5) == 'I') &&
3549 (NXT(6) == 'E') && (NXT(7) == 'S')) {
3550 SKIP(8);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003551 return(XML_ATTRIBUTE_ENTITIES);
Daniel Veillardcf461992000-03-14 18:30:20 +00003552 } else if ((RAW == 'N') && (NXT(1) == 'M') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003553 (NXT(2) == 'T') && (NXT(3) == 'O') &&
3554 (NXT(4) == 'K') && (NXT(5) == 'E') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003555 (NXT(6) == 'N') && (NXT(7) == 'S')) {
3556 SKIP(8);
3557 return(XML_ATTRIBUTE_NMTOKENS);
Daniel Veillardcf461992000-03-14 18:30:20 +00003558 } else if ((RAW == 'N') && (NXT(1) == 'M') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003559 (NXT(2) == 'T') && (NXT(3) == 'O') &&
3560 (NXT(4) == 'K') && (NXT(5) == 'E') &&
Daniel Veillard1e346af1999-02-22 10:33:01 +00003561 (NXT(6) == 'N')) {
3562 SKIP(7);
3563 return(XML_ATTRIBUTE_NMTOKEN);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003564 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003565 return(xmlParseEnumeratedType(ctxt, tree));
Daniel Veillard260a68f1998-08-13 03:39:55 +00003566}
3567
Daniel Veillard11e00581998-10-24 18:27:49 +00003568/**
3569 * xmlParseAttributeListDecl:
3570 * @ctxt: an XML parser context
3571 *
3572 * : parse the Attribute list def for an element
Daniel Veillard260a68f1998-08-13 03:39:55 +00003573 *
3574 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
3575 *
3576 * [53] AttDef ::= S Name S AttType S DefaultDecl
Daniel Veillard11e00581998-10-24 18:27:49 +00003577 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003578 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00003579void
3580xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003581 xmlChar *elemName;
3582 xmlChar *attrName;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003583 xmlEnumerationPtr tree;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003584
Daniel Veillardcf461992000-03-14 18:30:20 +00003585 if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00003586 (NXT(2) == 'A') && (NXT(3) == 'T') &&
3587 (NXT(4) == 'T') && (NXT(5) == 'L') &&
3588 (NXT(6) == 'I') && (NXT(7) == 'S') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003589 (NXT(8) == 'T')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003590 xmlParserInputPtr input = ctxt->input;
3591
Daniel Veillard260a68f1998-08-13 03:39:55 +00003592 SKIP(9);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003593 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003594 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003595 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003596 ctxt->sax->error(ctxt->userData,
3597 "Space required after '<!ATTLIST'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003598 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003599 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003600 }
3601 SKIP_BLANKS;
3602 elemName = xmlParseName(ctxt);
3603 if (elemName == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003604 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003605 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003606 ctxt->sax->error(ctxt->userData,
3607 "ATTLIST: no name for Element\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003608 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003609 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003610 return;
3611 }
3612 SKIP_BLANKS;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00003613 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00003614 while (RAW != '>') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003615 const xmlChar *check = CUR_PTR;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003616 int type;
3617 int def;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003618 xmlChar *defaultValue = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003619
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00003620 GROW;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003621 tree = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003622 attrName = xmlParseName(ctxt);
3623 if (attrName == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003624 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003625 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00003626 ctxt->sax->error(ctxt->userData,
3627 "ATTLIST: no name for Attribute\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003628 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003629 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003630 break;
3631 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003632 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003633 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003634 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003635 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003636 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003637 "Space required after the attribute name\n");
3638 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003639 ctxt->disableSAX = 1;
3640 if (attrName != NULL)
3641 xmlFree(attrName);
3642 if (defaultValue != NULL)
3643 xmlFree(defaultValue);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003644 break;
3645 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003646 SKIP_BLANKS;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003647
Daniel Veillard1e346af1999-02-22 10:33:01 +00003648 type = xmlParseAttributeType(ctxt, &tree);
Daniel Veillardcf461992000-03-14 18:30:20 +00003649 if (type <= 0) {
3650 if (attrName != NULL)
3651 xmlFree(attrName);
3652 if (defaultValue != NULL)
3653 xmlFree(defaultValue);
3654 break;
3655 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003656
Daniel Veillardb05deb71999-08-10 19:04:08 +00003657 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003658 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003659 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003660 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003661 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003662 "Space required after the attribute type\n");
3663 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003664 ctxt->disableSAX = 1;
3665 if (attrName != NULL)
3666 xmlFree(attrName);
3667 if (defaultValue != NULL)
3668 xmlFree(defaultValue);
3669 if (tree != NULL)
3670 xmlFreeEnumeration(tree);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003671 break;
3672 }
3673 SKIP_BLANKS;
3674
3675 def = xmlParseDefaultDecl(ctxt, &defaultValue);
Daniel Veillardcf461992000-03-14 18:30:20 +00003676 if (def <= 0) {
3677 if (attrName != NULL)
3678 xmlFree(attrName);
3679 if (defaultValue != NULL)
3680 xmlFree(defaultValue);
3681 if (tree != NULL)
3682 xmlFreeEnumeration(tree);
3683 break;
3684 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003685
Daniel Veillardb05deb71999-08-10 19:04:08 +00003686 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00003687 if (RAW != '>') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003688 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003689 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003690 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003691 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003692 "Space required after the attribute default value\n");
3693 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003694 ctxt->disableSAX = 1;
3695 if (attrName != NULL)
3696 xmlFree(attrName);
3697 if (defaultValue != NULL)
3698 xmlFree(defaultValue);
3699 if (tree != NULL)
3700 xmlFreeEnumeration(tree);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003701 break;
3702 }
3703 SKIP_BLANKS;
3704 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003705 if (check == CUR_PTR) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003706 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00003707 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003708 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003709 "xmlParseAttributeListDecl: detected internal error\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00003710 if (attrName != NULL)
3711 xmlFree(attrName);
3712 if (defaultValue != NULL)
3713 xmlFree(defaultValue);
3714 if (tree != NULL)
3715 xmlFreeEnumeration(tree);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003716 break;
3717 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003718 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
3719 (ctxt->sax->attributeDecl != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003720 ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
Daniel Veillard1e346af1999-02-22 10:33:01 +00003721 type, def, defaultValue, tree);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003722 if (attrName != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003723 xmlFree(attrName);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003724 if (defaultValue != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003725 xmlFree(defaultValue);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003726 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003727 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003728 if (RAW == '>') {
3729 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003730 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00003731 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3732 ctxt->sax->error(ctxt->userData,
3733"Attribute list declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00003734 ctxt->wellFormed = 0;
3735 ctxt->disableSAX = 1;
3736 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003737 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00003738 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003739
Daniel Veillard6454aec1999-09-02 22:04:43 +00003740 xmlFree(elemName);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003741 }
3742}
3743
Daniel Veillard11e00581998-10-24 18:27:49 +00003744/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003745 * xmlParseElementMixedContentDecl:
Daniel Veillard11e00581998-10-24 18:27:49 +00003746 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00003747 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003748 * parse the declaration for a Mixed Element content
3749 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
Daniel Veillard260a68f1998-08-13 03:39:55 +00003750 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003751 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
3752 * '(' S? '#PCDATA' S? ')'
3753 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003754 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
3755 *
3756 * [ VC: No Duplicate Types ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00003757 * The same name must not appear more than once in a single
3758 * mixed-content declaration.
Daniel Veillardb05deb71999-08-10 19:04:08 +00003759 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003760 * returns: the list of the xmlElementContentPtr describing the element choices
3761 */
3762xmlElementContentPtr
3763xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillard1899e851999-02-01 12:18:54 +00003764 xmlElementContentPtr ret = NULL, cur = NULL, n;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003765 xmlChar *elem = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003766
Daniel Veillardb05deb71999-08-10 19:04:08 +00003767 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00003768 if ((RAW == '#') && (NXT(1) == 'P') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003769 (NXT(2) == 'C') && (NXT(3) == 'D') &&
3770 (NXT(4) == 'A') && (NXT(5) == 'T') &&
3771 (NXT(6) == 'A')) {
3772 SKIP(7);
3773 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003774 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00003775 if (RAW == ')') {
3776 ctxt->entity = ctxt->input;
Daniel Veillard3b9def11999-01-31 22:15:06 +00003777 NEXT;
3778 ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
Daniel Veillardcf461992000-03-14 18:30:20 +00003779 if (RAW == '*') {
Daniel Veillardf600e251999-12-18 15:32:46 +00003780 ret->ocur = XML_ELEMENT_CONTENT_MULT;
3781 NEXT;
3782 }
Daniel Veillard3b9def11999-01-31 22:15:06 +00003783 return(ret);
3784 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003785 if ((RAW == '(') || (RAW == '|')) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003786 ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3787 if (ret == NULL) return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003788 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003789 while (RAW == '|') {
Daniel Veillard1899e851999-02-01 12:18:54 +00003790 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003791 if (elem == NULL) {
3792 ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3793 if (ret == NULL) return(NULL);
3794 ret->c1 = cur;
Daniel Veillard1899e851999-02-01 12:18:54 +00003795 cur = ret;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003796 } else {
Daniel Veillard1899e851999-02-01 12:18:54 +00003797 n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3798 if (n == NULL) return(NULL);
3799 n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3800 cur->c2 = n;
3801 cur = n;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003802 xmlFree(elem);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003803 }
3804 SKIP_BLANKS;
3805 elem = xmlParseName(ctxt);
3806 if (elem == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003807 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003808 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003809 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003810 "xmlParseElementMixedContentDecl : Name expected\n");
3811 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003812 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003813 xmlFreeElementContent(cur);
3814 return(NULL);
3815 }
3816 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003817 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003818 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003819 if ((RAW == ')') && (NXT(1) == '*')) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00003820 if (elem != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003821 cur->c2 = xmlNewElementContent(elem,
3822 XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003823 xmlFree(elem);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003824 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003825 ret->ocur = XML_ELEMENT_CONTENT_MULT;
Daniel Veillardcf461992000-03-14 18:30:20 +00003826 ctxt->entity = ctxt->input;
Daniel Veillard1899e851999-02-01 12:18:54 +00003827 SKIP(2);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003828 } else {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003829 if (elem != NULL) xmlFree(elem);
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003830 xmlFreeElementContent(ret);
3831 ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003832 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003833 ctxt->sax->error(ctxt->userData,
Daniel Veillard3b9def11999-01-31 22:15:06 +00003834 "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003835 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003836 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003837 return(NULL);
3838 }
3839
3840 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003841 ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003842 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003843 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003844 "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
3845 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003846 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003847 }
3848 return(ret);
3849}
3850
3851/**
3852 * xmlParseElementChildrenContentDecl:
3853 * @ctxt: an XML parser context
3854 *
3855 * parse the declaration for a Mixed Element content
3856 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
3857 *
3858 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003859 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
3860 *
3861 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
3862 *
3863 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
3864 *
3865 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
3866 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00003867 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
3868 * TODO Parameter-entity replacement text must be properly nested
3869 * with parenthetized groups. That is to say, if either of the
3870 * opening or closing parentheses in a choice, seq, or Mixed
3871 * construct is contained in the replacement text for a parameter
3872 * entity, both must be contained in the same replacement text. For
3873 * interoperability, if a parameter-entity reference appears in a
3874 * choice, seq, or Mixed construct, its replacement text should not
3875 * be empty, and neither the first nor last non-blank character of
3876 * the replacement text should be a connector (| or ,).
3877 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003878 * returns: the tree of xmlElementContentPtr describing the element
3879 * hierarchy.
3880 */
3881xmlElementContentPtr
3882xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
3883 xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003884 xmlChar *elem;
3885 xmlChar type = 0;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003886
3887 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003888 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00003889 if (RAW == '(') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003890 /* Recurse on first child */
3891 NEXT;
3892 SKIP_BLANKS;
3893 cur = ret = xmlParseElementChildrenContentDecl(ctxt);
3894 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003895 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003896 } else {
3897 elem = xmlParseName(ctxt);
3898 if (elem == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003899 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003900 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003901 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003902 "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
3903 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003904 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003905 return(NULL);
3906 }
3907 cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003908 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00003909 if (RAW == '?') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003910 cur->ocur = XML_ELEMENT_CONTENT_OPT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003911 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00003912 } else if (RAW == '*') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003913 cur->ocur = XML_ELEMENT_CONTENT_MULT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003914 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00003915 } else if (RAW == '+') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003916 cur->ocur = XML_ELEMENT_CONTENT_PLUS;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003917 NEXT;
3918 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00003919 cur->ocur = XML_ELEMENT_CONTENT_ONCE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003920 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00003921 xmlFree(elem);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003922 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003923 }
3924 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003925 SHRINK;
Daniel Veillardcf461992000-03-14 18:30:20 +00003926 while (RAW != ')') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003927 /*
3928 * Each loop we parse one separator and one element.
3929 */
Daniel Veillardcf461992000-03-14 18:30:20 +00003930 if (RAW == ',') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003931 if (type == 0) type = CUR;
3932
3933 /*
3934 * Detect "Name | Name , Name" error
3935 */
3936 else if (type != CUR) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003937 ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003938 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003939 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003940 "xmlParseElementChildrenContentDecl : '%c' expected\n",
3941 type);
3942 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003943 ctxt->disableSAX = 1;
3944 if ((op != NULL) && (op != ret))
3945 xmlFreeElementContent(op);
Daniel Veillard87b95392000-08-12 21:12:04 +00003946 if ((last != NULL) && (last != ret) &&
3947 (last != ret->c1) && (last != ret->c2))
Daniel Veillardcf461992000-03-14 18:30:20 +00003948 xmlFreeElementContent(last);
3949 if (ret != NULL)
3950 xmlFreeElementContent(ret);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003951 return(NULL);
3952 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003953 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003954
3955 op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
3956 if (op == NULL) {
3957 xmlFreeElementContent(ret);
3958 return(NULL);
3959 }
3960 if (last == NULL) {
3961 op->c1 = ret;
3962 ret = cur = op;
3963 } else {
3964 cur->c2 = op;
3965 op->c1 = last;
3966 cur =op;
Daniel Veillard1899e851999-02-01 12:18:54 +00003967 last = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003968 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003969 } else if (RAW == '|') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003970 if (type == 0) type = CUR;
3971
3972 /*
3973 * Detect "Name , Name | Name" error
3974 */
3975 else if (type != CUR) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00003976 ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003977 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00003978 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003979 "xmlParseElementChildrenContentDecl : '%c' expected\n",
3980 type);
3981 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00003982 ctxt->disableSAX = 1;
Daniel Veillard87b95392000-08-12 21:12:04 +00003983 if ((op != NULL) && (op != ret) && (op != last))
Daniel Veillardcf461992000-03-14 18:30:20 +00003984 xmlFreeElementContent(op);
Daniel Veillard87b95392000-08-12 21:12:04 +00003985 if ((last != NULL) && (last != ret) &&
3986 (last != ret->c1) && (last != ret->c2))
Daniel Veillardcf461992000-03-14 18:30:20 +00003987 xmlFreeElementContent(last);
3988 if (ret != NULL)
3989 xmlFreeElementContent(ret);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003990 return(NULL);
3991 }
Daniel Veillard1899e851999-02-01 12:18:54 +00003992 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003993
3994 op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3995 if (op == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003996 if ((op != NULL) && (op != ret))
3997 xmlFreeElementContent(op);
Daniel Veillard87b95392000-08-12 21:12:04 +00003998 if ((last != NULL) && (last != ret) &&
3999 (last != ret->c1) && (last != ret->c2))
Daniel Veillardcf461992000-03-14 18:30:20 +00004000 xmlFreeElementContent(last);
4001 if (ret != NULL)
4002 xmlFreeElementContent(ret);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004003 return(NULL);
4004 }
4005 if (last == NULL) {
4006 op->c1 = ret;
4007 ret = cur = op;
4008 } else {
4009 cur->c2 = op;
4010 op->c1 = last;
4011 cur =op;
Daniel Veillard1899e851999-02-01 12:18:54 +00004012 last = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004013 }
4014 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004015 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004016 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004017 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004018 "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
4019 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004020 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004021 if ((op != NULL) && (op != ret))
4022 xmlFreeElementContent(op);
Daniel Veillard87b95392000-08-12 21:12:04 +00004023 if ((last != NULL) && (last != ret) &&
4024 (last != ret->c1) && (last != ret->c2))
Daniel Veillardcf461992000-03-14 18:30:20 +00004025 xmlFreeElementContent(last);
4026 if (ret != NULL)
4027 xmlFreeElementContent(ret);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004028 return(NULL);
4029 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004030 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004031 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004032 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00004033 if (RAW == '(') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004034 /* Recurse on second child */
4035 NEXT;
4036 SKIP_BLANKS;
Daniel Veillard1899e851999-02-01 12:18:54 +00004037 last = xmlParseElementChildrenContentDecl(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004038 SKIP_BLANKS;
4039 } else {
4040 elem = xmlParseName(ctxt);
4041 if (elem == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004042 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004043 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004044 ctxt->sax->error(ctxt->userData,
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004045 "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004046 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004047 ctxt->disableSAX = 1;
4048 if ((op != NULL) && (op != ret))
4049 xmlFreeElementContent(op);
Daniel Veillard87b95392000-08-12 21:12:04 +00004050 if ((last != NULL) && (last != ret) &&
4051 (last != ret->c1) && (last != ret->c2))
Daniel Veillardcf461992000-03-14 18:30:20 +00004052 xmlFreeElementContent(last);
4053 if (ret != NULL)
4054 xmlFreeElementContent(ret);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004055 return(NULL);
4056 }
Daniel Veillard1899e851999-02-01 12:18:54 +00004057 last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004058 xmlFree(elem);
Daniel Veillardcf461992000-03-14 18:30:20 +00004059 if (RAW == '?') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004060 last->ocur = XML_ELEMENT_CONTENT_OPT;
4061 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004062 } else if (RAW == '*') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004063 last->ocur = XML_ELEMENT_CONTENT_MULT;
4064 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004065 } else if (RAW == '+') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004066 last->ocur = XML_ELEMENT_CONTENT_PLUS;
4067 NEXT;
4068 } else {
4069 last->ocur = XML_ELEMENT_CONTENT_ONCE;
4070 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004071 }
4072 SKIP_BLANKS;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004073 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004074 }
Daniel Veillard1899e851999-02-01 12:18:54 +00004075 if ((cur != NULL) && (last != NULL)) {
4076 cur->c2 = last;
4077 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004078 ctxt->entity = ctxt->input;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004079 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004080 if (RAW == '?') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004081 ret->ocur = XML_ELEMENT_CONTENT_OPT;
4082 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004083 } else if (RAW == '*') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004084 ret->ocur = XML_ELEMENT_CONTENT_MULT;
4085 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004086 } else if (RAW == '+') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004087 ret->ocur = XML_ELEMENT_CONTENT_PLUS;
4088 NEXT;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004089 }
4090 return(ret);
4091}
4092
4093/**
4094 * xmlParseElementContentDecl:
4095 * @ctxt: an XML parser context
4096 * @name: the name of the element being defined.
4097 * @result: the Element Content pointer will be stored here if any
Daniel Veillard260a68f1998-08-13 03:39:55 +00004098 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004099 * parse the declaration for an Element content either Mixed or Children,
4100 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
4101 *
4102 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
Daniel Veillard11e00581998-10-24 18:27:49 +00004103 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004104 * returns: the type of element content XML_ELEMENT_TYPE_xxx
Daniel Veillard260a68f1998-08-13 03:39:55 +00004105 */
4106
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004107int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004108xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004109 xmlElementContentPtr *result) {
4110
4111 xmlElementContentPtr tree = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00004112 xmlParserInputPtr input = ctxt->input;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004113 int res;
4114
4115 *result = NULL;
4116
Daniel Veillardcf461992000-03-14 18:30:20 +00004117 if (RAW != '(') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004118 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004119 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004120 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004121 "xmlParseElementContentDecl : '(' expected\n");
4122 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004123 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004124 return(-1);
4125 }
4126 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004127 GROW;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004128 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00004129 if ((RAW == '#') && (NXT(1) == 'P') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004130 (NXT(2) == 'C') && (NXT(3) == 'D') &&
4131 (NXT(4) == 'A') && (NXT(5) == 'T') &&
4132 (NXT(6) == 'A')) {
4133 tree = xmlParseElementMixedContentDecl(ctxt);
4134 res = XML_ELEMENT_TYPE_MIXED;
4135 } else {
4136 tree = xmlParseElementChildrenContentDecl(ctxt);
4137 res = XML_ELEMENT_TYPE_ELEMENT;
4138 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004139 if ((ctxt->entity != NULL) && (input != ctxt->entity)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004140 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00004141 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4142 ctxt->sax->error(ctxt->userData,
4143"Element content declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004144 ctxt->wellFormed = 0;
4145 ctxt->disableSAX = 1;
4146 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004147 SKIP_BLANKS;
Daniel Veillard3b9def11999-01-31 22:15:06 +00004148 *result = tree;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004149 return(res);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004150}
4151
Daniel Veillard11e00581998-10-24 18:27:49 +00004152/**
4153 * xmlParseElementDecl:
4154 * @ctxt: an XML parser context
4155 *
4156 * parse an Element declaration.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004157 *
4158 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
4159 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004160 * [ VC: Unique Element Type Declaration ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00004161 * No element type may be declared more than once
Daniel Veillard1e346af1999-02-22 10:33:01 +00004162 *
4163 * Returns the type of the element, or -1 in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +00004164 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004165int
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004166xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004167 xmlChar *name;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004168 int ret = -1;
4169 xmlElementContentPtr content = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004170
Daniel Veillardb05deb71999-08-10 19:04:08 +00004171 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00004172 if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00004173 (NXT(2) == 'E') && (NXT(3) == 'L') &&
4174 (NXT(4) == 'E') && (NXT(5) == 'M') &&
4175 (NXT(6) == 'E') && (NXT(7) == 'N') &&
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004176 (NXT(8) == 'T')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004177 xmlParserInputPtr input = ctxt->input;
4178
Daniel Veillard260a68f1998-08-13 03:39:55 +00004179 SKIP(9);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004180 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004181 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004182 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004183 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004184 "Space required after 'ELEMENT'\n");
4185 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004186 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004187 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004188 SKIP_BLANKS;
4189 name = xmlParseName(ctxt);
4190 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004191 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004192 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004193 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004194 "xmlParseElementDecl: no name for Element\n");
4195 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004196 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004197 return(-1);
4198 }
4199 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004200 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004201 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004202 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004203 "Space required after the element name\n");
4204 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004205 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004206 }
4207 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00004208 if ((RAW == 'E') && (NXT(1) == 'M') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00004209 (NXT(2) == 'P') && (NXT(3) == 'T') &&
4210 (NXT(4) == 'Y')) {
4211 SKIP(5);
4212 /*
4213 * Element must always be empty.
4214 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004215 ret = XML_ELEMENT_TYPE_EMPTY;
Daniel Veillardcf461992000-03-14 18:30:20 +00004216 } else if ((RAW == 'A') && (NXT(1) == 'N') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00004217 (NXT(2) == 'Y')) {
4218 SKIP(3);
4219 /*
4220 * Element is a generic container.
4221 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004222 ret = XML_ELEMENT_TYPE_ANY;
Daniel Veillardcf461992000-03-14 18:30:20 +00004223 } else if (RAW == '(') {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004224 ret = xmlParseElementContentDecl(ctxt, name, &content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004225 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004226 /*
4227 * [ WFC: PEs in Internal Subset ] error handling.
4228 */
Daniel Veillardcf461992000-03-14 18:30:20 +00004229 if ((RAW == '%') && (ctxt->external == 0) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00004230 (ctxt->inputNr == 1)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004231 ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004232 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4233 ctxt->sax->error(ctxt->userData,
4234 "PEReference: forbidden within markup decl in internal subset\n");
4235 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004236 ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004237 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4238 ctxt->sax->error(ctxt->userData,
4239 "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
4240 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004241 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004242 ctxt->disableSAX = 1;
Daniel Veillard6454aec1999-09-02 22:04:43 +00004243 if (name != NULL) xmlFree(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004244 return(-1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004245 }
Daniel Veillard686d6b62000-01-03 11:08:02 +00004246
Daniel Veillard260a68f1998-08-13 03:39:55 +00004247 SKIP_BLANKS;
Daniel Veillard686d6b62000-01-03 11:08:02 +00004248 /*
4249 * Pop-up of finished entities.
4250 */
Daniel Veillardcf461992000-03-14 18:30:20 +00004251 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillard686d6b62000-01-03 11:08:02 +00004252 xmlPopInput(ctxt);
4253 SKIP_BLANKS;
4254
Daniel Veillardcf461992000-03-14 18:30:20 +00004255 if (RAW != '>') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004256 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004257 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00004258 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00004259 "xmlParseElementDecl: expected '>' at the end\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004260 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004261 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004262 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00004263 if (input != ctxt->input) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004264 ctxt->errNo = XML_ERR_ENTITY_BOUNDARY;
Daniel Veillardcf461992000-03-14 18:30:20 +00004265 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4266 ctxt->sax->error(ctxt->userData,
4267"Element declaration doesn't start and stop in the same entity\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004268 ctxt->wellFormed = 0;
4269 ctxt->disableSAX = 1;
4270 }
4271
Daniel Veillard260a68f1998-08-13 03:39:55 +00004272 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004273 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
4274 (ctxt->sax->elementDecl != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00004275 ctxt->sax->elementDecl(ctxt->userData, name, ret,
4276 content);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004277 }
Daniel Veillard14fff061999-06-22 21:49:07 +00004278 if (content != NULL) {
4279 xmlFreeElementContent(content);
4280 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004281 if (name != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00004282 xmlFree(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004283 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004284 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004285 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004286}
4287
Daniel Veillard11e00581998-10-24 18:27:49 +00004288/**
4289 * xmlParseMarkupDecl:
4290 * @ctxt: an XML parser context
4291 *
4292 * parse Markup declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00004293 *
4294 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
4295 * NotationDecl | PI | Comment
4296 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004297 * [ VC: Proper Declaration/PE Nesting ]
Daniel Veillardb1059e22000-09-16 14:02:43 +00004298 * Parameter-entity replacement text must be properly nested with
Daniel Veillardb05deb71999-08-10 19:04:08 +00004299 * markup declarations. That is to say, if either the first character
4300 * or the last character of a markup declaration (markupdecl above) is
4301 * contained in the replacement text for a parameter-entity reference,
4302 * both must be contained in the same replacement text.
4303 *
4304 * [ WFC: PEs in Internal Subset ]
4305 * In the internal DTD subset, parameter-entity references can occur
4306 * only where markup declarations can occur, not within markup declarations.
4307 * (This does not apply to references that occur in external parameter
4308 * entities or to the external subset.)
Daniel Veillard260a68f1998-08-13 03:39:55 +00004309 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004310void
4311xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004312 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004313 xmlParseElementDecl(ctxt);
4314 xmlParseAttributeListDecl(ctxt);
4315 xmlParseEntityDecl(ctxt);
4316 xmlParseNotationDecl(ctxt);
4317 xmlParsePI(ctxt);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004318 xmlParseComment(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004319 /*
4320 * This is only for internal subset. On external entities,
4321 * the replacement is done before parsing stage
4322 */
4323 if ((ctxt->external == 0) && (ctxt->inputNr == 1))
4324 xmlParsePEReference(ctxt);
4325 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004326}
4327
Daniel Veillard11e00581998-10-24 18:27:49 +00004328/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004329 * xmlParseTextDecl:
4330 * @ctxt: an XML parser context
4331 *
4332 * parse an XML declaration header for external entities
4333 *
4334 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
4335 *
Daniel Veillardcf461992000-03-14 18:30:20 +00004336 * Question: Seems that EncodingDecl is mandatory ? Is that a typo ?
Daniel Veillard011b63c1999-06-02 17:44:04 +00004337 */
4338
Daniel Veillardcf461992000-03-14 18:30:20 +00004339void
Daniel Veillard011b63c1999-06-02 17:44:04 +00004340xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004341 xmlChar *version;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004342
4343 /*
4344 * We know that '<?xml' is here.
4345 */
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004346 if ((RAW == '<') && (NXT(1) == '?') &&
4347 (NXT(2) == 'x') && (NXT(3) == 'm') &&
4348 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
4349 SKIP(5);
4350 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004351 ctxt->errNo = XML_ERR_XMLDECL_NOT_STARTED;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004352 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4353 ctxt->sax->error(ctxt->userData,
4354 "Text declaration '<?xml' required\n");
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004355 ctxt->wellFormed = 0;
4356 ctxt->disableSAX = 1;
4357
4358 return;
4359 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004360
4361 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004362 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004363 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004364 ctxt->sax->error(ctxt->userData,
4365 "Space needed after '<?xml'\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004366 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004367 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004368 }
4369 SKIP_BLANKS;
4370
4371 /*
4372 * We may have the VersionInfo here.
4373 */
4374 version = xmlParseVersionInfo(ctxt);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004375 if (version == NULL)
4376 version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillardcf461992000-03-14 18:30:20 +00004377 ctxt->input->version = version;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004378
4379 /*
4380 * We must have the encoding declaration
4381 */
4382 if (!IS_BLANK(CUR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004383 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004384 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004385 ctxt->sax->error(ctxt->userData, "Space needed here\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004386 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004387 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004388 }
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004389 xmlParseEncodingDecl(ctxt);
4390 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
4391 /*
4392 * The XML REC instructs us to stop parsing right here
4393 */
4394 return;
4395 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004396
4397 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00004398 if ((RAW == '?') && (NXT(1) == '>')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004399 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00004400 } else if (RAW == '>') {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004401 /* Deprecated old WD ... */
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004402 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004403 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004404 ctxt->sax->error(ctxt->userData,
4405 "XML declaration must end-up with '?>'\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004406 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004407 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004408 NEXT;
4409 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004410 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004411 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00004412 ctxt->sax->error(ctxt->userData,
4413 "parsing XML declaration: '?>' expected\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004414 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004415 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004416 MOVETO_ENDTAG(CUR_PTR);
4417 NEXT;
4418 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004419}
4420
4421/*
4422 * xmlParseConditionalSections
4423 * @ctxt: an XML parser context
4424 *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004425 * [61] conditionalSect ::= includeSect | ignoreSect
4426 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
4427 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
4428 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
4429 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
4430 */
4431
4432void
4433xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004434 SKIP(3);
4435 SKIP_BLANKS;
4436 if ((RAW == 'I') && (NXT(1) == 'N') && (NXT(2) == 'C') &&
4437 (NXT(3) == 'L') && (NXT(4) == 'U') && (NXT(5) == 'D') &&
4438 (NXT(6) == 'E')) {
4439 SKIP(7);
4440 SKIP_BLANKS;
4441 if (RAW != '[') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004442 ctxt->errNo = XML_ERR_CONDSEC_INVALID;
Daniel Veillardcf461992000-03-14 18:30:20 +00004443 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4444 ctxt->sax->error(ctxt->userData,
4445 "XML conditional section '[' expected\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004446 ctxt->wellFormed = 0;
4447 ctxt->disableSAX = 1;
4448 } else {
4449 NEXT;
4450 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004451 if (xmlParserDebugEntities) {
4452 if ((ctxt->input != NULL) && (ctxt->input->filename))
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004453 xmlGenericError(xmlGenericErrorContext,
4454 "%s(%d): ", ctxt->input->filename,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004455 ctxt->input->line);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004456 xmlGenericError(xmlGenericErrorContext,
4457 "Entering INCLUDE Conditional Section\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004458 }
4459
Daniel Veillardcf461992000-03-14 18:30:20 +00004460 while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
4461 (NXT(2) != '>'))) {
4462 const xmlChar *check = CUR_PTR;
4463 int cons = ctxt->input->consumed;
4464 int tok = ctxt->token;
Daniel Veillard71b656e2000-01-05 14:46:17 +00004465
Daniel Veillardcf461992000-03-14 18:30:20 +00004466 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4467 xmlParseConditionalSections(ctxt);
4468 } else if (IS_BLANK(CUR)) {
4469 NEXT;
4470 } else if (RAW == '%') {
4471 xmlParsePEReference(ctxt);
4472 } else
4473 xmlParseMarkupDecl(ctxt);
4474
4475 /*
4476 * Pop-up of finished entities.
4477 */
4478 while ((RAW == 0) && (ctxt->inputNr > 1))
4479 xmlPopInput(ctxt);
4480
4481 if ((CUR_PTR == check) && (cons == ctxt->input->consumed) &&
4482 (tok == ctxt->token)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004483 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillardcf461992000-03-14 18:30:20 +00004484 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4485 ctxt->sax->error(ctxt->userData,
4486 "Content error in the external subset\n");
4487 ctxt->wellFormed = 0;
4488 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004489 break;
4490 }
4491 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004492 if (xmlParserDebugEntities) {
4493 if ((ctxt->input != NULL) && (ctxt->input->filename))
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004494 xmlGenericError(xmlGenericErrorContext,
4495 "%s(%d): ", ctxt->input->filename,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004496 ctxt->input->line);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004497 xmlGenericError(xmlGenericErrorContext,
4498 "Leaving INCLUDE Conditional Section\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004499 }
4500
Daniel Veillardcf461992000-03-14 18:30:20 +00004501 } else if ((RAW == 'I') && (NXT(1) == 'G') && (NXT(2) == 'N') &&
4502 (NXT(3) == 'O') && (NXT(4) == 'R') && (NXT(5) == 'E')) {
4503 int state;
4504
4505 SKIP(6);
4506 SKIP_BLANKS;
4507 if (RAW != '[') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004508 ctxt->errNo = XML_ERR_CONDSEC_INVALID;
Daniel Veillardcf461992000-03-14 18:30:20 +00004509 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4510 ctxt->sax->error(ctxt->userData,
4511 "XML conditional section '[' expected\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004512 ctxt->wellFormed = 0;
4513 ctxt->disableSAX = 1;
4514 } else {
4515 NEXT;
4516 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004517 if (xmlParserDebugEntities) {
4518 if ((ctxt->input != NULL) && (ctxt->input->filename))
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004519 xmlGenericError(xmlGenericErrorContext,
4520 "%s(%d): ", ctxt->input->filename,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004521 ctxt->input->line);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004522 xmlGenericError(xmlGenericErrorContext,
4523 "Entering IGNORE Conditional Section\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004524 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004525
4526 /*
4527 * Parse up to the end of the conditionnal section
4528 * But disable SAX event generating DTD building in the meantime
4529 */
4530 state = ctxt->disableSAX;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004531 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004532 while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
4533 (NXT(2) != '>'))) {
4534 const xmlChar *check = CUR_PTR;
4535 int cons = ctxt->input->consumed;
4536 int tok = ctxt->token;
4537
4538 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4539 xmlParseConditionalSections(ctxt);
4540 } else if (IS_BLANK(CUR)) {
4541 NEXT;
4542 } else if (RAW == '%') {
4543 xmlParsePEReference(ctxt);
4544 } else
4545 xmlParseMarkupDecl(ctxt);
4546
4547 /*
4548 * Pop-up of finished entities.
4549 */
4550 while ((RAW == 0) && (ctxt->inputNr > 1))
4551 xmlPopInput(ctxt);
4552
4553 if ((CUR_PTR == check) && (cons == ctxt->input->consumed) &&
4554 (tok == ctxt->token)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004555 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillardcf461992000-03-14 18:30:20 +00004556 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4557 ctxt->sax->error(ctxt->userData,
4558 "Content error in the external subset\n");
4559 ctxt->wellFormed = 0;
4560 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004561 break;
4562 }
4563 }
4564 ctxt->disableSAX = state;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004565 if (xmlParserDebugEntities) {
4566 if ((ctxt->input != NULL) && (ctxt->input->filename))
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004567 xmlGenericError(xmlGenericErrorContext,
4568 "%s(%d): ", ctxt->input->filename,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004569 ctxt->input->line);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00004570 xmlGenericError(xmlGenericErrorContext,
4571 "Leaving IGNORE Conditional Section\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004572 }
4573
Daniel Veillardcf461992000-03-14 18:30:20 +00004574 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004575 ctxt->errNo = XML_ERR_CONDSEC_INVALID;
Daniel Veillardcf461992000-03-14 18:30:20 +00004576 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4577 ctxt->sax->error(ctxt->userData,
4578 "XML conditional section INCLUDE or IGNORE keyword expected\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004579 ctxt->wellFormed = 0;
4580 ctxt->disableSAX = 1;
Daniel Veillard71b656e2000-01-05 14:46:17 +00004581 }
4582
Daniel Veillardcf461992000-03-14 18:30:20 +00004583 if (RAW == 0)
Daniel Veillard71b656e2000-01-05 14:46:17 +00004584 SHRINK;
4585
Daniel Veillardcf461992000-03-14 18:30:20 +00004586 if (RAW == 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004587 ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004588 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4589 ctxt->sax->error(ctxt->userData,
4590 "XML conditional section not closed\n");
4591 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004592 ctxt->disableSAX = 1;
Daniel Veillard71b656e2000-01-05 14:46:17 +00004593 } else {
4594 SKIP(3);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004595 }
4596}
4597
4598/**
Daniel Veillard00fdf371999-10-08 09:40:39 +00004599 * xmlParseExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004600 * @ctxt: an XML parser context
Daniel Veillard00fdf371999-10-08 09:40:39 +00004601 * @ExternalID: the external identifier
4602 * @SystemID: the system identifier (or URL)
Daniel Veillard011b63c1999-06-02 17:44:04 +00004603 *
4604 * parse Markup declarations from an external subset
4605 *
4606 * [30] extSubset ::= textDecl? extSubsetDecl
4607 *
4608 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004609 */
4610void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004611xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
4612 const xmlChar *SystemID) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00004613 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00004614 if ((RAW == '<') && (NXT(1) == '?') &&
Daniel Veillard011b63c1999-06-02 17:44:04 +00004615 (NXT(2) == 'x') && (NXT(3) == 'm') &&
4616 (NXT(4) == 'l')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004617 xmlParseTextDecl(ctxt);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004618 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
4619 /*
4620 * The XML REC instructs us to stop parsing right here
4621 */
4622 ctxt->instate = XML_PARSER_EOF;
4623 return;
4624 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004625 }
4626 if (ctxt->myDoc == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004627 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004628 }
4629 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
4630 xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
4631
Daniel Veillardb05deb71999-08-10 19:04:08 +00004632 ctxt->instate = XML_PARSER_DTD;
4633 ctxt->external = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004634 while (((RAW == '<') && (NXT(1) == '?')) ||
4635 ((RAW == '<') && (NXT(1) == '!')) ||
Daniel Veillard011b63c1999-06-02 17:44:04 +00004636 IS_BLANK(CUR)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004637 const xmlChar *check = CUR_PTR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004638 int cons = ctxt->input->consumed;
Daniel Veillardcf461992000-03-14 18:30:20 +00004639 int tok = ctxt->token;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004640
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00004641 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00004642 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004643 xmlParseConditionalSections(ctxt);
4644 } else if (IS_BLANK(CUR)) {
4645 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00004646 } else if (RAW == '%') {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004647 xmlParsePEReference(ctxt);
4648 } else
4649 xmlParseMarkupDecl(ctxt);
4650
4651 /*
4652 * Pop-up of finished entities.
4653 */
Daniel Veillardcf461992000-03-14 18:30:20 +00004654 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillard011b63c1999-06-02 17:44:04 +00004655 xmlPopInput(ctxt);
4656
Daniel Veillardcf461992000-03-14 18:30:20 +00004657 if ((CUR_PTR == check) && (cons == ctxt->input->consumed) &&
4658 (tok == ctxt->token)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004659 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004660 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4661 ctxt->sax->error(ctxt->userData,
4662 "Content error in the external subset\n");
4663 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004664 ctxt->disableSAX = 1;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004665 break;
4666 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004667 }
4668
Daniel Veillardcf461992000-03-14 18:30:20 +00004669 if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004670 ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004671 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4672 ctxt->sax->error(ctxt->userData,
4673 "Extra content at the end of the document\n");
4674 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004675 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004676 }
4677
4678}
4679
4680/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004681 * xmlParseReference:
4682 * @ctxt: an XML parser context
4683 *
4684 * parse and handle entity references in content, depending on the SAX
4685 * interface, this may end-up in a call to character() if this is a
4686 * CharRef, a predefined entity, if there is no reference() callback.
4687 * or if the parser was asked to switch to that mode.
4688 *
4689 * [67] Reference ::= EntityRef | CharRef
4690 */
4691void
4692xmlParseReference(xmlParserCtxtPtr ctxt) {
4693 xmlEntityPtr ent;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004694 xmlChar *val;
Daniel Veillardcf461992000-03-14 18:30:20 +00004695 if (RAW != '&') return;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004696
4697 if (NXT(1) == '#') {
Daniel Veillardcf461992000-03-14 18:30:20 +00004698 int i = 0;
4699 xmlChar out[10];
4700 int hex = NXT(2);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004701 int val = xmlParseCharRef(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00004702
Daniel Veillardbe803962000-06-28 23:40:59 +00004703 if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004704 /*
4705 * So we are using non-UTF-8 buffers
4706 * Check that the char fit on 8bits, if not
4707 * generate a CharRef.
4708 */
4709 if (val <= 0xFF) {
4710 out[0] = val;
4711 out[1] = 0;
4712 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
4713 (!ctxt->disableSAX))
4714 ctxt->sax->characters(ctxt->userData, out, 1);
4715 } else {
4716 if ((hex == 'x') || (hex == 'X'))
4717 sprintf((char *)out, "#x%X", val);
4718 else
4719 sprintf((char *)out, "#%d", val);
4720 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
4721 (!ctxt->disableSAX))
4722 ctxt->sax->reference(ctxt->userData, out);
4723 }
4724 } else {
4725 /*
4726 * Just encode the value in UTF-8
4727 */
4728 COPY_BUF(0 ,out, i, val);
4729 out[i] = 0;
4730 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
4731 (!ctxt->disableSAX))
4732 ctxt->sax->characters(ctxt->userData, out, i);
4733 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004734 } else {
4735 ent = xmlParseEntityRef(ctxt);
4736 if (ent == NULL) return;
4737 if ((ent->name != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00004738 (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
4739 xmlNodePtr list = NULL;
4740 int ret;
4741
4742
4743 /*
4744 * The first reference to the entity trigger a parsing phase
4745 * where the ent->children is filled with the result from
4746 * the parsing.
4747 */
4748 if (ent->children == NULL) {
4749 xmlChar *value;
4750 value = ent->content;
4751
4752 /*
4753 * Check that this entity is well formed
4754 */
4755 if ((value != NULL) &&
4756 (value[1] == 0) && (value[0] == '<') &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00004757 (xmlStrEqual(ent->name, BAD_CAST "lt"))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004758 /*
Daniel Veillarde0854c32000-08-27 21:12:29 +00004759 * DONE: get definite answer on this !!!
Daniel Veillardcf461992000-03-14 18:30:20 +00004760 * Lots of entity decls are used to declare a single
4761 * char
4762 * <!ENTITY lt "<">
4763 * Which seems to be valid since
4764 * 2.4: The ampersand character (&) and the left angle
4765 * bracket (<) may appear in their literal form only
4766 * when used ... They are also legal within the literal
4767 * entity value of an internal entity declaration;i
4768 * see "4.3.2 Well-Formed Parsed Entities".
4769 * IMHO 2.4 and 4.3.2 are directly in contradiction.
4770 * Looking at the OASIS test suite and James Clark
4771 * tests, this is broken. However the XML REC uses
4772 * it. Is the XML REC not well-formed ????
4773 * This is a hack to avoid this problem
Daniel Veillarde0854c32000-08-27 21:12:29 +00004774 *
4775 * ANSWER: since lt gt amp .. are already defined,
4776 * this is a redefinition and hence the fact that the
4777 * contentis not well balanced is not a Wf error, this
4778 * is lousy but acceptable.
Daniel Veillardcf461992000-03-14 18:30:20 +00004779 */
4780 list = xmlNewDocText(ctxt->myDoc, value);
4781 if (list != NULL) {
4782 if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
4783 (ent->children == NULL)) {
4784 ent->children = list;
4785 ent->last = list;
4786 list->parent = (xmlNodePtr) ent;
4787 } else {
4788 xmlFreeNodeList(list);
4789 }
4790 } else if (list != NULL) {
4791 xmlFreeNodeList(list);
4792 }
4793 } else {
4794 /*
4795 * 4.3.2: An internal general parsed entity is well-formed
4796 * if its replacement text matches the production labeled
4797 * content.
4798 */
4799 if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
4800 ctxt->depth++;
4801 ret = xmlParseBalancedChunkMemory(ctxt->myDoc,
4802 ctxt->sax, NULL, ctxt->depth,
4803 value, &list);
4804 ctxt->depth--;
4805 } else if (ent->etype ==
4806 XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
4807 ctxt->depth++;
4808 ret = xmlParseExternalEntity(ctxt->myDoc,
4809 ctxt->sax, NULL, ctxt->depth,
Daniel Veillard39c7d712000-09-10 16:14:55 +00004810 ent->URI, ent->ExternalID, &list);
Daniel Veillardcf461992000-03-14 18:30:20 +00004811 ctxt->depth--;
4812 } else {
4813 ret = -1;
4814 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4815 ctxt->sax->error(ctxt->userData,
4816 "Internal: invalid entity type\n");
4817 }
4818 if (ret == XML_ERR_ENTITY_LOOP) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004819 ctxt->errNo = XML_ERR_ENTITY_LOOP;
Daniel Veillardcf461992000-03-14 18:30:20 +00004820 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4821 ctxt->sax->error(ctxt->userData,
4822 "Detected entity reference loop\n");
4823 ctxt->wellFormed = 0;
4824 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00004825 } else if ((ret == 0) && (list != NULL)) {
4826 if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
4827 (ent->children == NULL)) {
4828 ent->children = list;
4829 while (list != NULL) {
4830 list->parent = (xmlNodePtr) ent;
4831 if (list->next == NULL)
4832 ent->last = list;
4833 list = list->next;
4834 }
4835 } else {
4836 xmlFreeNodeList(list);
4837 }
4838 } else if (ret > 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004839 ctxt->errNo = ret;
Daniel Veillardcf461992000-03-14 18:30:20 +00004840 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4841 ctxt->sax->error(ctxt->userData,
4842 "Entity value required\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004843 ctxt->wellFormed = 0;
4844 ctxt->disableSAX = 1;
4845 } else if (list != NULL) {
4846 xmlFreeNodeList(list);
4847 }
4848 }
4849 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004850 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00004851 (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004852 /*
4853 * Create a node.
4854 */
4855 ctxt->sax->reference(ctxt->userData, ent->name);
4856 return;
4857 } else if (ctxt->replaceEntities) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00004858 if ((ctxt->node != NULL) && (ent->children != NULL)) {
4859 /*
4860 * Seems we are generating the DOM content, do
4861 * a simple tree copy
4862 */
4863 xmlNodePtr new;
4864 new = xmlCopyNodeList(ent->children);
4865
4866 xmlAddChildList(ctxt->node, new);
4867 /*
4868 * This is to avoid a nasty side effect, see
4869 * characters() in SAX.c
4870 */
4871 ctxt->nodemem = 0;
4872 ctxt->nodelen = 0;
4873 return;
4874 } else {
4875 /*
4876 * Probably running in SAX mode
4877 */
4878 xmlParserInputPtr input;
Daniel Veillard011b63c1999-06-02 17:44:04 +00004879
Daniel Veillarde0854c32000-08-27 21:12:29 +00004880 input = xmlNewEntityInputStream(ctxt, ent);
4881 xmlPushInput(ctxt, input);
4882 if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) &&
4883 (RAW == '<') && (NXT(1) == '?') &&
4884 (NXT(2) == 'x') && (NXT(3) == 'm') &&
4885 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
4886 xmlParseTextDecl(ctxt);
4887 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
4888 /*
4889 * The XML REC instructs us to stop parsing right here
4890 */
4891 ctxt->instate = XML_PARSER_EOF;
4892 return;
4893 }
4894 if (input->standalone == 1) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004895 ctxt->errNo = XML_ERR_EXT_ENTITY_STANDALONE;
Daniel Veillarde0854c32000-08-27 21:12:29 +00004896 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4897 ctxt->sax->error(ctxt->userData,
4898 "external parsed entities cannot be standalone\n");
Daniel Veillarde0854c32000-08-27 21:12:29 +00004899 ctxt->wellFormed = 0;
4900 ctxt->disableSAX = 1;
4901 }
Daniel Veillard496a1cf2000-05-03 14:20:55 +00004902 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00004903 return;
Daniel Veillardcf461992000-03-14 18:30:20 +00004904 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004905 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00004906 } else {
4907 val = ent->content;
4908 if (val == NULL) return;
4909 /*
4910 * inline the entity.
4911 */
4912 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
4913 (!ctxt->disableSAX))
4914 ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
Daniel Veillard011b63c1999-06-02 17:44:04 +00004915 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004916 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004917}
4918
Daniel Veillard11e00581998-10-24 18:27:49 +00004919/**
4920 * xmlParseEntityRef:
4921 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00004922 *
4923 * parse ENTITY references declarations
Daniel Veillard260a68f1998-08-13 03:39:55 +00004924 *
4925 * [68] EntityRef ::= '&' Name ';'
Daniel Veillard1e346af1999-02-22 10:33:01 +00004926 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00004927 * [ WFC: Entity Declared ]
4928 * In a document without any DTD, a document with only an internal DTD
4929 * subset which contains no parameter entity references, or a document
4930 * with "standalone='yes'", the Name given in the entity reference
4931 * must match that in an entity declaration, except that well-formed
4932 * documents need not declare any of the following entities: amp, lt,
4933 * gt, apos, quot. The declaration of a parameter entity must precede
4934 * any reference to it. Similarly, the declaration of a general entity
4935 * must precede any reference to it which appears in a default value in an
4936 * attribute-list declaration. Note that if entities are declared in the
4937 * external subset or in external parameter entities, a non-validating
4938 * processor is not obligated to read and process their declarations;
4939 * for such documents, the rule that an entity must be declared is a
4940 * well-formedness constraint only if standalone='yes'.
4941 *
4942 * [ WFC: Parsed Entity ]
4943 * An entity reference must not contain the name of an unparsed entity
4944 *
Daniel Veillard011b63c1999-06-02 17:44:04 +00004945 * Returns the xmlEntityPtr if found, or NULL otherwise.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004946 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004947xmlEntityPtr
Daniel Veillard0ba4d531998-11-01 19:34:31 +00004948xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004949 xmlChar *name;
Daniel Veillard517752b1999-04-05 12:20:10 +00004950 xmlEntityPtr ent = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004951
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004952 GROW;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004953
Daniel Veillardcf461992000-03-14 18:30:20 +00004954 if (RAW == '&') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004955 NEXT;
4956 name = xmlParseName(ctxt);
4957 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00004958 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00004959 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00004960 ctxt->sax->error(ctxt->userData,
4961 "xmlParseEntityRef: no name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004962 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00004963 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004964 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00004965 if (RAW == ';') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004966 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004967 /*
Daniel Veillard011b63c1999-06-02 17:44:04 +00004968 * Ask first SAX for entity resolution, otherwise try the
4969 * predefined set.
4970 */
4971 if (ctxt->sax != NULL) {
4972 if (ctxt->sax->getEntity != NULL)
4973 ent = ctxt->sax->getEntity(ctxt->userData, name);
4974 if (ent == NULL)
4975 ent = xmlGetPredefinedEntity(name);
4976 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00004977 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00004978 * [ WFC: Entity Declared ]
4979 * In a document without any DTD, a document with only an
4980 * internal DTD subset which contains no parameter entity
4981 * references, or a document with "standalone='yes'", the
4982 * Name given in the entity reference must match that in an
4983 * entity declaration, except that well-formed documents
4984 * need not declare any of the following entities: amp, lt,
4985 * gt, apos, quot.
4986 * The declaration of a parameter entity must precede any
4987 * reference to it.
4988 * Similarly, the declaration of a general entity must
4989 * precede any reference to it which appears in a default
4990 * value in an attribute-list declaration. Note that if
4991 * entities are declared in the external subset or in
4992 * external parameter entities, a non-validating processor
4993 * is not obligated to read and process their declarations;
4994 * for such documents, the rule that an entity must be
4995 * declared is a well-formedness constraint only if
4996 * standalone='yes'.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004997 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00004998 if (ent == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00004999 if ((ctxt->standalone == 1) ||
5000 ((ctxt->hasExternalSubset == 0) &&
5001 (ctxt->hasPErefs == 0))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005002 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005003 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard011b63c1999-06-02 17:44:04 +00005004 ctxt->sax->error(ctxt->userData,
5005 "Entity '%s' not defined\n", name);
5006 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005007 ctxt->disableSAX = 1;
Daniel Veillard011b63c1999-06-02 17:44:04 +00005008 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005009 ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005010 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5011 ctxt->sax->warning(ctxt->userData,
5012 "Entity '%s' not defined\n", name);
Daniel Veillard011b63c1999-06-02 17:44:04 +00005013 }
5014 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005015
5016 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005017 * [ WFC: Parsed Entity ]
5018 * An entity reference must not contain the name of an
5019 * unparsed entity
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005020 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005021 else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005022 ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005023 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5024 ctxt->sax->error(ctxt->userData,
5025 "Entity reference to unparsed entity %s\n", name);
5026 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005027 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005028 }
5029
5030 /*
5031 * [ WFC: No External Entity References ]
5032 * Attribute values cannot contain direct or indirect
5033 * entity references to external entities.
5034 */
5035 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00005036 (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005037 ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005038 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5039 ctxt->sax->error(ctxt->userData,
5040 "Attribute references external entity '%s'\n", name);
5041 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005042 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005043 }
5044 /*
5045 * [ WFC: No < in Attribute Values ]
5046 * The replacement text of any entity referred to directly or
5047 * indirectly in an attribute value (other than "&lt;") must
5048 * not contain a <.
5049 */
5050 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
Daniel Veillardb96e6431999-08-29 21:02:19 +00005051 (ent != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005052 (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +00005053 (ent->content != NULL) &&
5054 (xmlStrchr(ent->content, '<'))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005055 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005056 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5057 ctxt->sax->error(ctxt->userData,
5058 "'<' in entity '%s' is not allowed in attributes values\n", name);
5059 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005060 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005061 }
5062
5063 /*
5064 * Internal check, no parameter entities here ...
5065 */
5066 else {
Daniel Veillardcf461992000-03-14 18:30:20 +00005067 switch (ent->etype) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005068 case XML_INTERNAL_PARAMETER_ENTITY:
5069 case XML_EXTERNAL_PARAMETER_ENTITY:
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005070 ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005071 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005072 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005073 "Attempt to reference the parameter entity '%s'\n", name);
5074 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005075 ctxt->disableSAX = 1;
5076 break;
5077 default:
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005078 break;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005079 }
5080 }
5081
5082 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005083 * [ WFC: No Recursion ]
Daniel Veillardb1059e22000-09-16 14:02:43 +00005084 * A parsed entity must not contain a recursive reference
Daniel Veillardb96e6431999-08-29 21:02:19 +00005085 * to itself, either directly or indirectly.
Daniel Veillardb1059e22000-09-16 14:02:43 +00005086 * Done somewhere else
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005087 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00005088
Daniel Veillard011b63c1999-06-02 17:44:04 +00005089 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005090 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005091 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005092 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005093 "xmlParseEntityRef: expecting ';'\n");
5094 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005095 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005096 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00005097 xmlFree(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005098 }
5099 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00005100 return(ent);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005101}
Daniel Veillardb1059e22000-09-16 14:02:43 +00005102
Daniel Veillard10a2c651999-12-12 13:03:50 +00005103/**
5104 * xmlParseStringEntityRef:
5105 * @ctxt: an XML parser context
5106 * @str: a pointer to an index in the string
5107 *
5108 * parse ENTITY references declarations, but this version parses it from
5109 * a string value.
5110 *
5111 * [68] EntityRef ::= '&' Name ';'
5112 *
5113 * [ WFC: Entity Declared ]
5114 * In a document without any DTD, a document with only an internal DTD
5115 * subset which contains no parameter entity references, or a document
5116 * with "standalone='yes'", the Name given in the entity reference
5117 * must match that in an entity declaration, except that well-formed
5118 * documents need not declare any of the following entities: amp, lt,
5119 * gt, apos, quot. The declaration of a parameter entity must precede
5120 * any reference to it. Similarly, the declaration of a general entity
5121 * must precede any reference to it which appears in a default value in an
5122 * attribute-list declaration. Note that if entities are declared in the
5123 * external subset or in external parameter entities, a non-validating
5124 * processor is not obligated to read and process their declarations;
5125 * for such documents, the rule that an entity must be declared is a
5126 * well-formedness constraint only if standalone='yes'.
5127 *
5128 * [ WFC: Parsed Entity ]
5129 * An entity reference must not contain the name of an unparsed entity
5130 *
5131 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
5132 * is updated to the current location in the string.
5133 */
5134xmlEntityPtr
5135xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
5136 xmlChar *name;
5137 const xmlChar *ptr;
5138 xmlChar cur;
5139 xmlEntityPtr ent = NULL;
5140
Daniel Veillardcf461992000-03-14 18:30:20 +00005141 if ((str == NULL) || (*str == NULL))
5142 return(NULL);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005143 ptr = *str;
5144 cur = *ptr;
5145 if (cur == '&') {
5146 ptr++;
5147 cur = *ptr;
5148 name = xmlParseStringName(ctxt, &ptr);
5149 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005150 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005151 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5152 ctxt->sax->error(ctxt->userData,
5153 "xmlParseEntityRef: no name\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00005154 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005155 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005156 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00005157 if (*ptr == ';') {
5158 ptr++;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005159 /*
5160 * Ask first SAX for entity resolution, otherwise try the
5161 * predefined set.
5162 */
5163 if (ctxt->sax != NULL) {
5164 if (ctxt->sax->getEntity != NULL)
5165 ent = ctxt->sax->getEntity(ctxt->userData, name);
5166 if (ent == NULL)
5167 ent = xmlGetPredefinedEntity(name);
5168 }
5169 /*
5170 * [ WFC: Entity Declared ]
5171 * In a document without any DTD, a document with only an
5172 * internal DTD subset which contains no parameter entity
5173 * references, or a document with "standalone='yes'", the
5174 * Name given in the entity reference must match that in an
5175 * entity declaration, except that well-formed documents
5176 * need not declare any of the following entities: amp, lt,
5177 * gt, apos, quot.
5178 * The declaration of a parameter entity must precede any
5179 * reference to it.
5180 * Similarly, the declaration of a general entity must
5181 * precede any reference to it which appears in a default
5182 * value in an attribute-list declaration. Note that if
5183 * entities are declared in the external subset or in
5184 * external parameter entities, a non-validating processor
5185 * is not obligated to read and process their declarations;
5186 * for such documents, the rule that an entity must be
5187 * declared is a well-formedness constraint only if
5188 * standalone='yes'.
5189 */
5190 if (ent == NULL) {
5191 if ((ctxt->standalone == 1) ||
5192 ((ctxt->hasExternalSubset == 0) &&
5193 (ctxt->hasPErefs == 0))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005194 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005195 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5196 ctxt->sax->error(ctxt->userData,
5197 "Entity '%s' not defined\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005198 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005199 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005200 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005201 ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005202 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5203 ctxt->sax->warning(ctxt->userData,
5204 "Entity '%s' not defined\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005205 }
5206 }
5207
5208 /*
5209 * [ WFC: Parsed Entity ]
5210 * An entity reference must not contain the name of an
5211 * unparsed entity
5212 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005213 else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005214 ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005215 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5216 ctxt->sax->error(ctxt->userData,
5217 "Entity reference to unparsed entity %s\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005218 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005219 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005220 }
5221
5222 /*
5223 * [ WFC: No External Entity References ]
5224 * Attribute values cannot contain direct or indirect
5225 * entity references to external entities.
5226 */
5227 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00005228 (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005229 ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005230 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5231 ctxt->sax->error(ctxt->userData,
5232 "Attribute references external entity '%s'\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005233 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005234 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005235 }
5236 /*
5237 * [ WFC: No < in Attribute Values ]
5238 * The replacement text of any entity referred to directly or
5239 * indirectly in an attribute value (other than "&lt;") must
5240 * not contain a <.
5241 */
5242 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
5243 (ent != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005244 (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
Daniel Veillard10a2c651999-12-12 13:03:50 +00005245 (ent->content != NULL) &&
5246 (xmlStrchr(ent->content, '<'))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005247 ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005248 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5249 ctxt->sax->error(ctxt->userData,
5250 "'<' in entity '%s' is not allowed in attributes values\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005251 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005252 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005253 }
5254
5255 /*
5256 * Internal check, no parameter entities here ...
5257 */
5258 else {
Daniel Veillardcf461992000-03-14 18:30:20 +00005259 switch (ent->etype) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00005260 case XML_INTERNAL_PARAMETER_ENTITY:
5261 case XML_EXTERNAL_PARAMETER_ENTITY:
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005262 ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005263 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5264 ctxt->sax->error(ctxt->userData,
5265 "Attempt to reference the parameter entity '%s'\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005266 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005267 ctxt->disableSAX = 1;
5268 break;
5269 default:
Daniel Veillard10a2c651999-12-12 13:03:50 +00005270 break;
5271 }
5272 }
5273
5274 /*
5275 * [ WFC: No Recursion ]
Daniel Veillardb1059e22000-09-16 14:02:43 +00005276 * A parsed entity must not contain a recursive reference
Daniel Veillard10a2c651999-12-12 13:03:50 +00005277 * to itself, either directly or indirectly.
Daniel Veillardb1059e22000-09-16 14:02:43 +00005278 * Done somewhwere else
Daniel Veillard10a2c651999-12-12 13:03:50 +00005279 */
5280
5281 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005282 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005283 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5284 ctxt->sax->error(ctxt->userData,
5285 "xmlParseEntityRef: expecting ';'\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00005286 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005287 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005288 }
5289 xmlFree(name);
5290 }
5291 }
Daniel Veillardcf461992000-03-14 18:30:20 +00005292 *str = ptr;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005293 return(ent);
5294}
Daniel Veillard260a68f1998-08-13 03:39:55 +00005295
Daniel Veillard11e00581998-10-24 18:27:49 +00005296/**
5297 * xmlParsePEReference:
5298 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00005299 *
5300 * parse PEReference declarations
Daniel Veillard011b63c1999-06-02 17:44:04 +00005301 * The entity content is handled directly by pushing it's content as
5302 * a new input stream.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005303 *
5304 * [69] PEReference ::= '%' Name ';'
Daniel Veillard1e346af1999-02-22 10:33:01 +00005305 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005306 * [ WFC: No Recursion ]
Daniel Veillardb1059e22000-09-16 14:02:43 +00005307 * A parsed entity must not contain a recursive
Daniel Veillardb05deb71999-08-10 19:04:08 +00005308 * reference to itself, either directly or indirectly.
5309 *
5310 * [ WFC: Entity Declared ]
5311 * In a document without any DTD, a document with only an internal DTD
5312 * subset which contains no parameter entity references, or a document
5313 * with "standalone='yes'", ... ... The declaration of a parameter
5314 * entity must precede any reference to it...
5315 *
5316 * [ VC: Entity Declared ]
5317 * In a document with an external subset or external parameter entities
5318 * with "standalone='no'", ... ... The declaration of a parameter entity
5319 * must precede any reference to it...
5320 *
5321 * [ WFC: In DTD ]
5322 * Parameter-entity references may only appear in the DTD.
5323 * NOTE: misleading but this is handled.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005324 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00005325void
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005326xmlParsePEReference(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005327 xmlChar *name;
Daniel Veillard517752b1999-04-05 12:20:10 +00005328 xmlEntityPtr entity = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00005329 xmlParserInputPtr input;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005330
Daniel Veillardcf461992000-03-14 18:30:20 +00005331 if (RAW == '%') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005332 NEXT;
5333 name = xmlParseName(ctxt);
5334 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005335 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005336 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005337 ctxt->sax->error(ctxt->userData,
5338 "xmlParsePEReference: no name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005339 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005340 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005341 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00005342 if (RAW == ';') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005343 NEXT;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005344 if ((ctxt->sax != NULL) &&
5345 (ctxt->sax->getParameterEntity != NULL))
5346 entity = ctxt->sax->getParameterEntity(ctxt->userData,
5347 name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005348 if (entity == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005349 /*
5350 * [ WFC: Entity Declared ]
5351 * In a document without any DTD, a document with only an
5352 * internal DTD subset which contains no parameter entity
5353 * references, or a document with "standalone='yes'", ...
5354 * ... The declaration of a parameter entity must precede
5355 * any reference to it...
5356 */
5357 if ((ctxt->standalone == 1) ||
5358 ((ctxt->hasExternalSubset == 0) &&
5359 (ctxt->hasPErefs == 0))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005360 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00005361 if ((!ctxt->disableSAX) &&
5362 (ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00005363 ctxt->sax->error(ctxt->userData,
5364 "PEReference: %%%s; not found\n", name);
5365 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005366 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005367 } else {
5368 /*
5369 * [ VC: Entity Declared ]
5370 * In a document with an external subset or external
5371 * parameter entities with "standalone='no'", ...
5372 * ... The declaration of a parameter entity must precede
5373 * any reference to it...
5374 */
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00005375 if ((!ctxt->disableSAX) &&
5376 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00005377 ctxt->sax->warning(ctxt->userData,
5378 "PEReference: %%%s; not found\n", name);
5379 ctxt->valid = 0;
5380 }
Daniel Veillardccb09631998-10-27 06:21:04 +00005381 } else {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005382 /*
5383 * Internal checking in case the entity quest barfed
5384 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005385 if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
5386 (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005387 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5388 ctxt->sax->warning(ctxt->userData,
5389 "Internal: %%%s; is not a parameter entity\n", name);
5390 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00005391 /*
5392 * TODO !!!
5393 * handle the extra spaces added before and after
5394 * c.f. http://www.w3.org/TR/REC-xml#as-PE
5395 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00005396 input = xmlNewEntityInputStream(ctxt, entity);
5397 xmlPushInput(ctxt, input);
Daniel Veillardcf461992000-03-14 18:30:20 +00005398 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
5399 (RAW == '<') && (NXT(1) == '?') &&
5400 (NXT(2) == 'x') && (NXT(3) == 'm') &&
5401 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
5402 xmlParseTextDecl(ctxt);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00005403 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
5404 /*
5405 * The XML REC instructs us to stop parsing
5406 * right here
5407 */
5408 ctxt->instate = XML_PARSER_EOF;
5409 xmlFree(name);
5410 return;
5411 }
Daniel Veillardcf461992000-03-14 18:30:20 +00005412 }
5413 if (ctxt->token == 0)
5414 ctxt->token = ' ';
Daniel Veillardb05deb71999-08-10 19:04:08 +00005415 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005416 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00005417 ctxt->hasPErefs = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005418 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005419 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005420 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005421 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005422 "xmlParsePEReference: expecting ';'\n");
5423 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005424 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005425 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00005426 xmlFree(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005427 }
5428 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005429}
5430
Daniel Veillard11e00581998-10-24 18:27:49 +00005431/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00005432 * xmlParseStringPEReference:
5433 * @ctxt: an XML parser context
5434 * @str: a pointer to an index in the string
5435 *
5436 * parse PEReference declarations
5437 *
5438 * [69] PEReference ::= '%' Name ';'
5439 *
5440 * [ WFC: No Recursion ]
Daniel Veillardb1059e22000-09-16 14:02:43 +00005441 * A parsed entity must not contain a recursive
Daniel Veillard10a2c651999-12-12 13:03:50 +00005442 * reference to itself, either directly or indirectly.
5443 *
5444 * [ WFC: Entity Declared ]
5445 * In a document without any DTD, a document with only an internal DTD
5446 * subset which contains no parameter entity references, or a document
5447 * with "standalone='yes'", ... ... The declaration of a parameter
5448 * entity must precede any reference to it...
5449 *
5450 * [ VC: Entity Declared ]
5451 * In a document with an external subset or external parameter entities
5452 * with "standalone='no'", ... ... The declaration of a parameter entity
5453 * must precede any reference to it...
5454 *
5455 * [ WFC: In DTD ]
5456 * Parameter-entity references may only appear in the DTD.
5457 * NOTE: misleading but this is handled.
5458 *
5459 * Returns the string of the entity content.
5460 * str is updated to the current value of the index
5461 */
5462xmlEntityPtr
5463xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
5464 const xmlChar *ptr;
5465 xmlChar cur;
5466 xmlChar *name;
5467 xmlEntityPtr entity = NULL;
5468
5469 if ((str == NULL) || (*str == NULL)) return(NULL);
5470 ptr = *str;
5471 cur = *ptr;
5472 if (cur == '%') {
5473 ptr++;
5474 cur = *ptr;
5475 name = xmlParseStringName(ctxt, &ptr);
5476 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005477 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005478 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5479 ctxt->sax->error(ctxt->userData,
5480 "xmlParseStringPEReference: no name\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00005481 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005482 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005483 } else {
5484 cur = *ptr;
5485 if (cur == ';') {
5486 ptr++;
5487 cur = *ptr;
5488 if ((ctxt->sax != NULL) &&
5489 (ctxt->sax->getParameterEntity != NULL))
5490 entity = ctxt->sax->getParameterEntity(ctxt->userData,
5491 name);
5492 if (entity == NULL) {
5493 /*
5494 * [ WFC: Entity Declared ]
5495 * In a document without any DTD, a document with only an
5496 * internal DTD subset which contains no parameter entity
5497 * references, or a document with "standalone='yes'", ...
5498 * ... The declaration of a parameter entity must precede
5499 * any reference to it...
5500 */
5501 if ((ctxt->standalone == 1) ||
5502 ((ctxt->hasExternalSubset == 0) &&
5503 (ctxt->hasPErefs == 0))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005504 ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005505 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5506 ctxt->sax->error(ctxt->userData,
5507 "PEReference: %%%s; not found\n", name);
Daniel Veillard10a2c651999-12-12 13:03:50 +00005508 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005509 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005510 } else {
5511 /*
5512 * [ VC: Entity Declared ]
5513 * In a document with an external subset or external
5514 * parameter entities with "standalone='no'", ...
5515 * ... The declaration of a parameter entity must
5516 * precede any reference to it...
5517 */
5518 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5519 ctxt->sax->warning(ctxt->userData,
5520 "PEReference: %%%s; not found\n", name);
5521 ctxt->valid = 0;
5522 }
5523 } else {
5524 /*
5525 * Internal checking in case the entity quest barfed
5526 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005527 if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
5528 (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00005529 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5530 ctxt->sax->warning(ctxt->userData,
5531 "Internal: %%%s; is not a parameter entity\n", name);
5532 }
5533 }
5534 ctxt->hasPErefs = 1;
5535 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005536 ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005537 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5538 ctxt->sax->error(ctxt->userData,
5539 "xmlParseStringPEReference: expecting ';'\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +00005540 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005541 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00005542 }
5543 xmlFree(name);
5544 }
5545 }
5546 *str = ptr;
5547 return(entity);
5548}
5549
5550/**
Daniel Veillardcf461992000-03-14 18:30:20 +00005551 * xmlParseDocTypeDecl:
Daniel Veillard11e00581998-10-24 18:27:49 +00005552 * @ctxt: an XML parser context
5553 *
5554 * parse a DOCTYPE declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00005555 *
5556 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
5557 * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
Daniel Veillardb05deb71999-08-10 19:04:08 +00005558 *
5559 * [ VC: Root Element Type ]
5560 * The Name in the document type declaration must match the element
5561 * type of the root element.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005562 */
5563
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005564void
5565xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillardcf461992000-03-14 18:30:20 +00005566 xmlChar *name = NULL;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005567 xmlChar *ExternalID = NULL;
5568 xmlChar *URI = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005569
5570 /*
5571 * We know that '<!DOCTYPE' has been detected.
5572 */
5573 SKIP(9);
5574
5575 SKIP_BLANKS;
5576
5577 /*
5578 * Parse the DOCTYPE name.
5579 */
5580 name = xmlParseName(ctxt);
5581 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005582 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005583 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00005584 ctxt->sax->error(ctxt->userData,
5585 "xmlParseDocTypeDecl : no DOCTYPE name !\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005586 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005587 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005588 }
Daniel Veillardcf461992000-03-14 18:30:20 +00005589 ctxt->intSubName = name;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005590
5591 SKIP_BLANKS;
5592
5593 /*
5594 * Check for SystemID and ExternalID
5595 */
Daniel Veillard1e346af1999-02-22 10:33:01 +00005596 URI = xmlParseExternalID(ctxt, &ExternalID, 1);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005597
5598 if ((URI != NULL) || (ExternalID != NULL)) {
5599 ctxt->hasExternalSubset = 1;
5600 }
Daniel Veillardcf461992000-03-14 18:30:20 +00005601 ctxt->extSubURI = URI;
5602 ctxt->extSubSystem = ExternalID;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005603
Daniel Veillard260a68f1998-08-13 03:39:55 +00005604 SKIP_BLANKS;
5605
Daniel Veillard011b63c1999-06-02 17:44:04 +00005606 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00005607 * Create and update the internal subset.
Daniel Veillard011b63c1999-06-02 17:44:04 +00005608 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005609 if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
5610 (!ctxt->disableSAX))
Daniel Veillard27d88741999-05-29 11:51:49 +00005611 ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005612
5613 /*
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005614 * Is there any internal subset declarations ?
5615 * they are handled separately in xmlParseInternalSubset()
5616 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005617 if (RAW == '[')
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005618 return;
5619
5620 /*
5621 * We should be at the end of the DOCTYPE declaration.
5622 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005623 if (RAW != '>') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005624 ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005625 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5626 ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
5627 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005628 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005629 }
5630 NEXT;
5631}
5632
5633/**
Daniel Veillardcf461992000-03-14 18:30:20 +00005634 * xmlParseInternalsubset:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005635 * @ctxt: an XML parser context
5636 *
5637 * parse the internal subset declaration
5638 *
5639 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
5640 */
5641
5642void
5643xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
5644 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00005645 * Is there any DTD definition ?
5646 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005647 if (RAW == '[') {
Daniel Veillardb05deb71999-08-10 19:04:08 +00005648 ctxt->instate = XML_PARSER_DTD;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005649 NEXT;
5650 /*
5651 * Parse the succession of Markup declarations and
5652 * PEReferences.
5653 * Subsequence (markupdecl | PEReference | S)*
5654 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005655 while (RAW != ']') {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005656 const xmlChar *check = CUR_PTR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00005657 int cons = ctxt->input->consumed;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005658
5659 SKIP_BLANKS;
5660 xmlParseMarkupDecl(ctxt);
Daniel Veillardccb09631998-10-27 06:21:04 +00005661 xmlParsePEReference(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005662
Daniel Veillard011b63c1999-06-02 17:44:04 +00005663 /*
5664 * Pop-up of finished entities.
5665 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005666 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillard011b63c1999-06-02 17:44:04 +00005667 xmlPopInput(ctxt);
5668
Daniel Veillardc26087b1999-08-30 11:23:51 +00005669 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005670 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillardb96e6431999-08-29 21:02:19 +00005671 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5672 ctxt->sax->error(ctxt->userData,
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005673 "xmlParseInternalSubset: error detected in Markup declaration\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00005674 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005675 ctxt->disableSAX = 1;
Daniel Veillardb96e6431999-08-29 21:02:19 +00005676 break;
5677 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005678 }
Daniel Veillard36650692000-07-21 15:16:39 +00005679 if (RAW == ']') {
5680 NEXT;
5681 SKIP_BLANKS;
5682 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005683 }
5684
5685 /*
5686 * We should be at the end of the DOCTYPE declaration.
5687 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005688 if (RAW != '>') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005689 ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005690 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005691 ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005692 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005693 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005694 }
5695 NEXT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005696}
5697
Daniel Veillard11e00581998-10-24 18:27:49 +00005698/**
5699 * xmlParseAttribute:
5700 * @ctxt: an XML parser context
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005701 * @value: a xmlChar ** used to store the value of the attribute
Daniel Veillard11e00581998-10-24 18:27:49 +00005702 *
5703 * parse an attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00005704 *
5705 * [41] Attribute ::= Name Eq AttValue
5706 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005707 * [ WFC: No External Entity References ]
5708 * Attribute values cannot contain direct or indirect entity references
5709 * to external entities.
5710 *
5711 * [ WFC: No < in Attribute Values ]
5712 * The replacement text of any entity referred to directly or indirectly in
5713 * an attribute value (other than "&lt;") must not contain a <.
5714 *
5715 * [ VC: Attribute Value Type ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00005716 * The attribute must have been declared; the value must be of the type
Daniel Veillardb05deb71999-08-10 19:04:08 +00005717 * declared for it.
5718 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00005719 * [25] Eq ::= S? '=' S?
5720 *
5721 * With namespace:
5722 *
5723 * [NS 11] Attribute ::= QName Eq AttValue
5724 *
5725 * Also the case QName == xmlns:??? is handled independently as a namespace
5726 * definition.
Daniel Veillard1e346af1999-02-22 10:33:01 +00005727 *
Daniel Veillard517752b1999-04-05 12:20:10 +00005728 * Returns the attribute name, and the value in *value.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005729 */
5730
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005731xmlChar *
5732xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
5733 xmlChar *name, *val;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005734
Daniel Veillard517752b1999-04-05 12:20:10 +00005735 *value = NULL;
5736 name = xmlParseName(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005737 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005738 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005739 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005740 ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005741 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005742 ctxt->disableSAX = 1;
Daniel Veillardccb09631998-10-27 06:21:04 +00005743 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005744 }
5745
5746 /*
5747 * read the value
5748 */
5749 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00005750 if (RAW == '=') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00005751 NEXT;
5752 SKIP_BLANKS;
Daniel Veillard517752b1999-04-05 12:20:10 +00005753 val = xmlParseAttValue(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005754 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005755 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005756 ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005757 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005758 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005759 "Specification mandate value for attribute %s\n", name);
5760 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005761 ctxt->disableSAX = 1;
5762 xmlFree(name);
Daniel Veillardccb09631998-10-27 06:21:04 +00005763 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005764 }
5765
Daniel Veillardcf461992000-03-14 18:30:20 +00005766 /*
5767 * Check that xml:lang conforms to the specification
Daniel Veillarde0854c32000-08-27 21:12:29 +00005768 * No more registered as an error, just generate a warning now
5769 * since this was deprecated in XML second edition
Daniel Veillardcf461992000-03-14 18:30:20 +00005770 */
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005771 if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00005772 if (!xmlCheckLanguageID(val)) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00005773 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
5774 ctxt->sax->warning(ctxt->userData,
5775 "Malformed value for xml:lang : %s\n", val);
Daniel Veillardcf461992000-03-14 18:30:20 +00005776 }
5777 }
5778
5779 /*
5780 * Check that xml:space conforms to the specification
5781 */
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005782 if (xmlStrEqual(name, BAD_CAST "xml:space")) {
5783 if (xmlStrEqual(val, BAD_CAST "default"))
Daniel Veillardcf461992000-03-14 18:30:20 +00005784 *(ctxt->space) = 0;
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005785 else if (xmlStrEqual(val, BAD_CAST "preserve"))
Daniel Veillardcf461992000-03-14 18:30:20 +00005786 *(ctxt->space) = 1;
5787 else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005788 ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
Daniel Veillardcf461992000-03-14 18:30:20 +00005789 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5790 ctxt->sax->error(ctxt->userData,
5791"Invalid value for xml:space : \"%s\", \"default\" or \"preserve\" expected\n",
5792 val);
Daniel Veillardcf461992000-03-14 18:30:20 +00005793 ctxt->wellFormed = 0;
5794 ctxt->disableSAX = 1;
5795 }
5796 }
5797
Daniel Veillard517752b1999-04-05 12:20:10 +00005798 *value = val;
5799 return(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005800}
5801
Daniel Veillard11e00581998-10-24 18:27:49 +00005802/**
5803 * xmlParseStartTag:
5804 * @ctxt: an XML parser context
5805 *
5806 * parse a start of tag either for rule element or
5807 * EmptyElement. In both case we don't parse the tag closing chars.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005808 *
5809 * [40] STag ::= '<' Name (S Attribute)* S? '>'
5810 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005811 * [ WFC: Unique Att Spec ]
5812 * No attribute name may appear more than once in the same start-tag or
5813 * empty-element tag.
5814 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00005815 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
5816 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00005817 * [ WFC: Unique Att Spec ]
5818 * No attribute name may appear more than once in the same start-tag or
5819 * empty-element tag.
5820 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00005821 * With namespace:
5822 *
5823 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
5824 *
5825 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
Daniel Veillard14fff061999-06-22 21:49:07 +00005826 *
Daniel Veillard06047432000-04-24 11:33:38 +00005827 * Returns the element name parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +00005828 */
5829
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005830xmlChar *
Daniel Veillard1e346af1999-02-22 10:33:01 +00005831xmlParseStartTag(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005832 xmlChar *name;
5833 xmlChar *attname;
5834 xmlChar *attvalue;
5835 const xmlChar **atts = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00005836 int nbatts = 0;
5837 int maxatts = 0;
5838 int i;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005839
Daniel Veillardcf461992000-03-14 18:30:20 +00005840 if (RAW != '<') return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005841 NEXT;
5842
Daniel Veillard517752b1999-04-05 12:20:10 +00005843 name = xmlParseName(ctxt);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005844 if (name == NULL) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005845 ctxt->errNo = XML_ERR_NAME_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005846 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005847 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005848 "xmlParseStartTag: invalid element name\n");
5849 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005850 ctxt->disableSAX = 1;
Daniel Veillard14fff061999-06-22 21:49:07 +00005851 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005852 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005853
5854 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00005855 * Now parse the attributes, it ends up with the ending
5856 *
5857 * (S Attribute)* S?
5858 */
5859 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005860 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00005861
5862 while ((IS_CHAR(RAW)) &&
5863 (RAW != '>') &&
5864 ((RAW != '/') || (NXT(1) != '>'))) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005865 const xmlChar *q = CUR_PTR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005866 int cons = ctxt->input->consumed;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005867
Daniel Veillard517752b1999-04-05 12:20:10 +00005868 attname = xmlParseAttribute(ctxt, &attvalue);
5869 if ((attname != NULL) && (attvalue != NULL)) {
5870 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00005871 * [ WFC: Unique Att Spec ]
5872 * No attribute name may appear more than once in the same
5873 * start-tag or empty-element tag.
Daniel Veillard517752b1999-04-05 12:20:10 +00005874 */
5875 for (i = 0; i < nbatts;i += 2) {
Daniel Veillard8b5dd832000-10-01 20:28:44 +00005876 if (xmlStrEqual(atts[i], attname)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005877 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
Daniel Veillard517752b1999-04-05 12:20:10 +00005878 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillardb05deb71999-08-10 19:04:08 +00005879 ctxt->sax->error(ctxt->userData,
5880 "Attribute %s redefined\n",
5881 attname);
Daniel Veillard517752b1999-04-05 12:20:10 +00005882 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005883 ctxt->disableSAX = 1;
Daniel Veillard6454aec1999-09-02 22:04:43 +00005884 xmlFree(attname);
5885 xmlFree(attvalue);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005886 goto failed;
Daniel Veillard517752b1999-04-05 12:20:10 +00005887 }
5888 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00005889
Daniel Veillard517752b1999-04-05 12:20:10 +00005890 /*
5891 * Add the pair to atts
5892 */
5893 if (atts == NULL) {
5894 maxatts = 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005895 atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
Daniel Veillard517752b1999-04-05 12:20:10 +00005896 if (atts == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00005897 xmlGenericError(xmlGenericErrorContext,
5898 "malloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005899 maxatts * (long)sizeof(xmlChar *));
Daniel Veillard14fff061999-06-22 21:49:07 +00005900 return(NULL);
Daniel Veillard517752b1999-04-05 12:20:10 +00005901 }
Daniel Veillard51e3b151999-11-12 17:02:31 +00005902 } else if (nbatts + 4 > maxatts) {
Daniel Veillard517752b1999-04-05 12:20:10 +00005903 maxatts *= 2;
Daniel Veillard4b0755c2000-09-25 14:26:28 +00005904 atts = (const xmlChar **) xmlRealloc((void *) atts,
5905 maxatts * sizeof(xmlChar *));
Daniel Veillard517752b1999-04-05 12:20:10 +00005906 if (atts == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00005907 xmlGenericError(xmlGenericErrorContext,
5908 "realloc of %ld byte failed\n",
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005909 maxatts * (long)sizeof(xmlChar *));
Daniel Veillard14fff061999-06-22 21:49:07 +00005910 return(NULL);
Daniel Veillard517752b1999-04-05 12:20:10 +00005911 }
5912 }
5913 atts[nbatts++] = attname;
5914 atts[nbatts++] = attvalue;
5915 atts[nbatts] = NULL;
5916 atts[nbatts + 1] = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00005917 } else {
5918 if (attname != NULL)
5919 xmlFree(attname);
5920 if (attvalue != NULL)
5921 xmlFree(attvalue);
Daniel Veillard517752b1999-04-05 12:20:10 +00005922 }
5923
Daniel Veillardb96e6431999-08-29 21:02:19 +00005924failed:
Daniel Veillardcf461992000-03-14 18:30:20 +00005925
5926 if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
5927 break;
5928 if (!IS_BLANK(RAW)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005929 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillardcf461992000-03-14 18:30:20 +00005930 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5931 ctxt->sax->error(ctxt->userData,
5932 "attributes construct error\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00005933 ctxt->wellFormed = 0;
5934 ctxt->disableSAX = 1;
5935 }
Daniel Veillard517752b1999-04-05 12:20:10 +00005936 SKIP_BLANKS;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005937 if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005938 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005939 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005940 ctxt->sax->error(ctxt->userData,
Daniel Veillard260a68f1998-08-13 03:39:55 +00005941 "xmlParseStartTag: problem parsing attributes\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005942 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005943 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005944 break;
5945 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005946 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005947 }
5948
5949 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00005950 * SAX: Start of Element !
5951 */
Daniel Veillardcf461992000-03-14 18:30:20 +00005952 if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
5953 (!ctxt->disableSAX))
Daniel Veillard27d88741999-05-29 11:51:49 +00005954 ctxt->sax->startElement(ctxt->userData, name, atts);
Daniel Veillard517752b1999-04-05 12:20:10 +00005955
Daniel Veillard517752b1999-04-05 12:20:10 +00005956 if (atts != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005957 for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
Daniel Veillard4b0755c2000-09-25 14:26:28 +00005958 xmlFree((void *) atts);
Daniel Veillard517752b1999-04-05 12:20:10 +00005959 }
Daniel Veillard14fff061999-06-22 21:49:07 +00005960 return(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005961}
5962
Daniel Veillard11e00581998-10-24 18:27:49 +00005963/**
5964 * xmlParseEndTag:
5965 * @ctxt: an XML parser context
Daniel Veillard11e00581998-10-24 18:27:49 +00005966 *
5967 * parse an end of tag
Daniel Veillard260a68f1998-08-13 03:39:55 +00005968 *
5969 * [42] ETag ::= '</' Name S? '>'
5970 *
5971 * With namespace
5972 *
Daniel Veillard517752b1999-04-05 12:20:10 +00005973 * [NS 9] ETag ::= '</' QName S? '>'
Daniel Veillard260a68f1998-08-13 03:39:55 +00005974 */
5975
Daniel Veillard0ba4d531998-11-01 19:34:31 +00005976void
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005977xmlParseEndTag(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005978 xmlChar *name;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005979 xmlChar *oldname;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005980
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005981 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00005982 if ((RAW != '<') || (NXT(1) != '/')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00005983 ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00005984 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00005985 ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005986 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00005987 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005988 return;
5989 }
5990 SKIP(2);
5991
Daniel Veillard517752b1999-04-05 12:20:10 +00005992 name = xmlParseName(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005993
5994 /*
5995 * We should definitely be at the ending "S? '>'" part
5996 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00005997 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00005998 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00005999 if ((!IS_CHAR(RAW)) || (RAW != '>')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006000 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006001 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006002 ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006003 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006004 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006005 } else
6006 NEXT;
6007
Daniel Veillard517752b1999-04-05 12:20:10 +00006008 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00006009 * [ WFC: Element Type Match ]
6010 * The Name in an element's end-tag must match the element type in the
6011 * start-tag.
6012 *
Daniel Veillard14fff061999-06-22 21:49:07 +00006013 */
Daniel Veillardda07c342000-01-25 18:31:22 +00006014 if ((name == NULL) || (ctxt->name == NULL) ||
Daniel Veillard8b5dd832000-10-01 20:28:44 +00006015 (!xmlStrEqual(name, ctxt->name))) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006016 ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
Daniel Veillardda07c342000-01-25 18:31:22 +00006017 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
6018 if ((name != NULL) && (ctxt->name != NULL)) {
6019 ctxt->sax->error(ctxt->userData,
6020 "Opening and ending tag mismatch: %s and %s\n",
6021 ctxt->name, name);
6022 } else if (ctxt->name != NULL) {
6023 ctxt->sax->error(ctxt->userData,
6024 "Ending tag eror for: %s\n", ctxt->name);
6025 } else {
6026 ctxt->sax->error(ctxt->userData,
6027 "Ending tag error: internal error ???\n");
6028 }
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006029
Daniel Veillardda07c342000-01-25 18:31:22 +00006030 }
Daniel Veillard14fff061999-06-22 21:49:07 +00006031 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006032 ctxt->disableSAX = 1;
Daniel Veillard14fff061999-06-22 21:49:07 +00006033 }
6034
6035 /*
Daniel Veillard517752b1999-04-05 12:20:10 +00006036 * SAX: End of Tag
6037 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006038 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
6039 (!ctxt->disableSAX))
Daniel Veillard27d88741999-05-29 11:51:49 +00006040 ctxt->sax->endElement(ctxt->userData, name);
Daniel Veillard517752b1999-04-05 12:20:10 +00006041
6042 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00006043 xmlFree(name);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006044 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006045 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006046 if (oldname != NULL) {
6047#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006048 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006049#endif
6050 xmlFree(oldname);
6051 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006052 return;
6053}
6054
Daniel Veillard11e00581998-10-24 18:27:49 +00006055/**
6056 * xmlParseCDSect:
6057 * @ctxt: an XML parser context
6058 *
6059 * Parse escaped pure raw content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006060 *
6061 * [18] CDSect ::= CDStart CData CDEnd
6062 *
6063 * [19] CDStart ::= '<![CDATA['
6064 *
6065 * [20] Data ::= (Char* - (Char* ']]>' Char*))
6066 *
6067 * [21] CDEnd ::= ']]>'
6068 */
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006069void
6070xmlParseCDSect(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006071 xmlChar *buf = NULL;
6072 int len = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006073 int size = XML_PARSER_BUFFER_SIZE;
Daniel Veillardcf461992000-03-14 18:30:20 +00006074 int r, rl;
6075 int s, sl;
6076 int cur, l;
Daniel Veillardf09e7e32000-10-01 15:53:30 +00006077 int count = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006078
Daniel Veillardb05deb71999-08-10 19:04:08 +00006079 if ((NXT(0) == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006080 (NXT(2) == '[') && (NXT(3) == 'C') &&
6081 (NXT(4) == 'D') && (NXT(5) == 'A') &&
6082 (NXT(6) == 'T') && (NXT(7) == 'A') &&
6083 (NXT(8) == '[')) {
6084 SKIP(9);
6085 } else
6086 return;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006087
6088 ctxt->instate = XML_PARSER_CDATA_SECTION;
Daniel Veillardcf461992000-03-14 18:30:20 +00006089 r = CUR_CHAR(rl);
6090 if (!IS_CHAR(r)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006091 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006092 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006093 ctxt->sax->error(ctxt->userData,
Daniel Veillard10a2c651999-12-12 13:03:50 +00006094 "CData section not finished\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006095 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006096 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006097 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006098 return;
6099 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006100 NEXTL(rl);
6101 s = CUR_CHAR(sl);
6102 if (!IS_CHAR(s)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006103 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006104 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006105 ctxt->sax->error(ctxt->userData,
Daniel Veillard10a2c651999-12-12 13:03:50 +00006106 "CData section not finished\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006107 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006108 ctxt->disableSAX = 1;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006109 ctxt->instate = XML_PARSER_CONTENT;
6110 return;
6111 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006112 NEXTL(sl);
6113 cur = CUR_CHAR(l);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006114 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
6115 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006116 xmlGenericError(xmlGenericErrorContext,
6117 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006118 return;
6119 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00006120 while (IS_CHAR(cur) &&
6121 ((r != ']') || (s != ']') || (cur != '>'))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00006122 if (len + 5 >= size) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006123 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00006124 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00006125 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006126 xmlGenericError(xmlGenericErrorContext,
6127 "realloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006128 return;
6129 }
6130 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006131 COPY_BUF(rl,buf,len,r);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006132 r = s;
Daniel Veillardcf461992000-03-14 18:30:20 +00006133 rl = sl;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006134 s = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00006135 sl = l;
Daniel Veillardf09e7e32000-10-01 15:53:30 +00006136 count++;
6137 if (count > 50) {
6138 GROW;
6139 count = 0;
6140 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006141 NEXTL(l);
6142 cur = CUR_CHAR(l);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006143 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00006144 buf[len] = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006145 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006146 if (cur != '>') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006147 ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
Daniel Veillardb05deb71999-08-10 19:04:08 +00006148 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006149 ctxt->sax->error(ctxt->userData,
Daniel Veillard10a2c651999-12-12 13:03:50 +00006150 "CData section not finished\n%.50s\n", buf);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006151 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006152 ctxt->disableSAX = 1;
Daniel Veillard10a2c651999-12-12 13:03:50 +00006153 xmlFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006154 return;
6155 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006156 NEXTL(l);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006157
6158 /*
Daniel Veillard10a2c651999-12-12 13:03:50 +00006159 * Ok the buffer is to be consumed as cdata.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006160 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006161 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00006162 if (ctxt->sax->cdataBlock != NULL)
Daniel Veillard10a2c651999-12-12 13:03:50 +00006163 ctxt->sax->cdataBlock(ctxt->userData, buf, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006164 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00006165 xmlFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006166}
6167
Daniel Veillard11e00581998-10-24 18:27:49 +00006168/**
6169 * xmlParseContent:
6170 * @ctxt: an XML parser context
6171 *
6172 * Parse a content:
Daniel Veillard260a68f1998-08-13 03:39:55 +00006173 *
6174 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
6175 */
6176
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006177void
6178xmlParseContent(xmlParserCtxtPtr ctxt) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00006179 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00006180 while (((RAW != 0) || (ctxt->token != 0)) &&
6181 ((RAW != '<') || (NXT(1) != '/'))) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006182 const xmlChar *test = CUR_PTR;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006183 int cons = ctxt->input->consumed;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006184 xmlChar tok = ctxt->token;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006185
6186 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00006187 * Handle possible processed charrefs.
6188 */
6189 if (ctxt->token != 0) {
6190 xmlParseCharData(ctxt, 0);
6191 }
6192 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00006193 * First case : a Processing Instruction.
6194 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006195 else if ((RAW == '<') && (NXT(1) == '?')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006196 xmlParsePI(ctxt);
6197 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006198
Daniel Veillard260a68f1998-08-13 03:39:55 +00006199 /*
6200 * Second case : a CDSection
6201 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006202 else if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006203 (NXT(2) == '[') && (NXT(3) == 'C') &&
6204 (NXT(4) == 'D') && (NXT(5) == 'A') &&
6205 (NXT(6) == 'T') && (NXT(7) == 'A') &&
6206 (NXT(8) == '[')) {
6207 xmlParseCDSect(ctxt);
6208 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006209
Daniel Veillard260a68f1998-08-13 03:39:55 +00006210 /*
6211 * Third case : a comment
6212 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006213 else if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006214 (NXT(2) == '-') && (NXT(3) == '-')) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00006215 xmlParseComment(ctxt);
Daniel Veillardb05deb71999-08-10 19:04:08 +00006216 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006217 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006218
Daniel Veillard260a68f1998-08-13 03:39:55 +00006219 /*
6220 * Fourth case : a sub-element.
6221 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006222 else if (RAW == '<') {
Daniel Veillard517752b1999-04-05 12:20:10 +00006223 xmlParseElement(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006224 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006225
Daniel Veillard260a68f1998-08-13 03:39:55 +00006226 /*
Daniel Veillardccb09631998-10-27 06:21:04 +00006227 * Fifth case : a reference. If if has not been resolved,
6228 * parsing returns it's Name, create the node
Daniel Veillard260a68f1998-08-13 03:39:55 +00006229 */
Daniel Veillardb05deb71999-08-10 19:04:08 +00006230
Daniel Veillardcf461992000-03-14 18:30:20 +00006231 else if (RAW == '&') {
Daniel Veillard011b63c1999-06-02 17:44:04 +00006232 xmlParseReference(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006233 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006234
Daniel Veillard260a68f1998-08-13 03:39:55 +00006235 /*
6236 * Last case, text. Note that References are handled directly.
6237 */
6238 else {
6239 xmlParseCharData(ctxt, 0);
6240 }
6241
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006242 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006243 /*
6244 * Pop-up of finished entities.
6245 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006246 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillardbc50b591999-03-01 12:28:53 +00006247 xmlPopInput(ctxt);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006248 SHRINK;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006249
Daniel Veillardb96e6431999-08-29 21:02:19 +00006250 if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
6251 (tok == ctxt->token)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006252 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006253 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006254 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006255 "detected an error in element content\n");
6256 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006257 ctxt->disableSAX = 1;
Daniel Veillarde715dd22000-08-29 18:29:38 +00006258 ctxt->instate = XML_PARSER_EOF;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006259 break;
6260 }
6261 }
6262}
6263
Daniel Veillard11e00581998-10-24 18:27:49 +00006264/**
6265 * xmlParseElement:
6266 * @ctxt: an XML parser context
6267 *
6268 * parse an XML element, this is highly recursive
Daniel Veillard260a68f1998-08-13 03:39:55 +00006269 *
6270 * [39] element ::= EmptyElemTag | STag content ETag
6271 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00006272 * [ WFC: Element Type Match ]
6273 * The Name in an element's end-tag must match the element type in the
6274 * start-tag.
6275 *
6276 * [ VC: Element Valid ]
Daniel Veillardb96e6431999-08-29 21:02:19 +00006277 * An element is valid if there is a declaration matching elementdecl
Daniel Veillardb05deb71999-08-10 19:04:08 +00006278 * where the Name matches the element type and one of the following holds:
6279 * - The declaration matches EMPTY and the element has no content.
6280 * - The declaration matches children and the sequence of child elements
6281 * belongs to the language generated by the regular expression in the
6282 * content model, with optional white space (characters matching the
6283 * nonterminal S) between each pair of child elements.
6284 * - The declaration matches Mixed and the content consists of character
6285 * data and child elements whose types match names in the content model.
6286 * - The declaration matches ANY, and the types of any child elements have
6287 * been declared.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006288 */
6289
Daniel Veillard517752b1999-04-05 12:20:10 +00006290void
Daniel Veillard1e346af1999-02-22 10:33:01 +00006291xmlParseElement(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006292 const xmlChar *openTag = CUR_PTR;
6293 xmlChar *name;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006294 xmlChar *oldname;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006295 xmlParserNodeInfo node_info;
Daniel Veillardc26087b1999-08-30 11:23:51 +00006296 xmlNodePtr ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006297
6298 /* Capture start position */
Daniel Veillardc26087b1999-08-30 11:23:51 +00006299 if (ctxt->record_info) {
6300 node_info.begin_pos = ctxt->input->consumed +
6301 (CUR_PTR - ctxt->input->base);
6302 node_info.begin_line = ctxt->input->line;
6303 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006304
Daniel Veillardcf461992000-03-14 18:30:20 +00006305 if (ctxt->spaceNr == 0)
6306 spacePush(ctxt, -1);
6307 else
6308 spacePush(ctxt, *ctxt->space);
6309
Daniel Veillard14fff061999-06-22 21:49:07 +00006310 name = xmlParseStartTag(ctxt);
6311 if (name == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00006312 spacePop(ctxt);
Daniel Veillard14fff061999-06-22 21:49:07 +00006313 return;
6314 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006315 namePush(ctxt, name);
Daniel Veillardc26087b1999-08-30 11:23:51 +00006316 ret = ctxt->node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006317
6318 /*
Daniel Veillardb05deb71999-08-10 19:04:08 +00006319 * [ VC: Root Element Type ]
6320 * The Name in the document type declaration must match the element
6321 * type of the root element.
6322 */
6323 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
Daniel Veillardcf461992000-03-14 18:30:20 +00006324 ctxt->node && (ctxt->node == ctxt->myDoc->children))
Daniel Veillardb05deb71999-08-10 19:04:08 +00006325 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
6326
6327 /*
Daniel Veillard260a68f1998-08-13 03:39:55 +00006328 * Check for an Empty Element.
6329 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006330 if ((RAW == '/') && (NXT(1) == '>')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006331 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00006332 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
6333 (!ctxt->disableSAX))
Daniel Veillard14fff061999-06-22 21:49:07 +00006334 ctxt->sax->endElement(ctxt->userData, name);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006335 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006336 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006337 if (oldname != NULL) {
6338#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006339 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006340#endif
6341 xmlFree(oldname);
6342 }
Daniel Veillard87b95392000-08-12 21:12:04 +00006343 if ( ret != NULL && ctxt->record_info ) {
6344 node_info.end_pos = ctxt->input->consumed +
6345 (CUR_PTR - ctxt->input->base);
6346 node_info.end_line = ctxt->input->line;
6347 node_info.node = ret;
6348 xmlParserAddNodeInfo(ctxt, &node_info);
6349 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006350 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006351 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006352 if (RAW == '>') {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006353 NEXT;
6354 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006355 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006356 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006357 ctxt->sax->error(ctxt->userData,
6358 "Couldn't find end of Start Tag\n%.30s\n",
Daniel Veillard242590e1998-11-13 18:04:35 +00006359 openTag);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006360 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006361 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006362
6363 /*
6364 * end of parsing of this node.
6365 */
6366 nodePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006367 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006368 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006369 if (oldname != NULL) {
6370#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006371 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006372#endif
6373 xmlFree(oldname);
6374 }
Daniel Veillardc26087b1999-08-30 11:23:51 +00006375
6376 /*
6377 * Capture end position and add node
6378 */
6379 if ( ret != NULL && ctxt->record_info ) {
6380 node_info.end_pos = ctxt->input->consumed +
6381 (CUR_PTR - ctxt->input->base);
6382 node_info.end_line = ctxt->input->line;
6383 node_info.node = ret;
6384 xmlParserAddNodeInfo(ctxt, &node_info);
6385 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006386 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006387 }
6388
6389 /*
6390 * Parse the content of the element:
6391 */
6392 xmlParseContent(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006393 if (!IS_CHAR(RAW)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006394 ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006395 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006396 ctxt->sax->error(ctxt->userData,
Daniel Veillard242590e1998-11-13 18:04:35 +00006397 "Premature end of data in tag %.30s\n", openTag);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006398 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006399 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006400
6401 /*
6402 * end of parsing of this node.
6403 */
6404 nodePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006405 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006406 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006407 if (oldname != NULL) {
6408#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006409 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006410#endif
6411 xmlFree(oldname);
6412 }
Daniel Veillard517752b1999-04-05 12:20:10 +00006413 return;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006414 }
6415
6416 /*
6417 * parse the end of tag: '</' should be here.
6418 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00006419 xmlParseEndTag(ctxt);
Daniel Veillardc26087b1999-08-30 11:23:51 +00006420
6421 /*
6422 * Capture end position and add node
6423 */
6424 if ( ret != NULL && ctxt->record_info ) {
6425 node_info.end_pos = ctxt->input->consumed +
6426 (CUR_PTR - ctxt->input->base);
6427 node_info.end_line = ctxt->input->line;
6428 node_info.node = ret;
6429 xmlParserAddNodeInfo(ctxt, &node_info);
6430 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006431}
6432
Daniel Veillard11e00581998-10-24 18:27:49 +00006433/**
6434 * xmlParseVersionNum:
6435 * @ctxt: an XML parser context
6436 *
6437 * parse the XML version value.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006438 *
6439 * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
Daniel Veillard1e346af1999-02-22 10:33:01 +00006440 *
6441 * Returns the string giving the XML version number, or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006442 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006443xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006444xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006445 xmlChar *buf = NULL;
6446 int len = 0;
6447 int size = 10;
6448 xmlChar cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006449
Daniel Veillard10a2c651999-12-12 13:03:50 +00006450 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
6451 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006452 xmlGenericError(xmlGenericErrorContext,
6453 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006454 return(NULL);
6455 }
6456 cur = CUR;
Daniel Veillardcf461992000-03-14 18:30:20 +00006457 while (((cur >= 'a') && (cur <= 'z')) ||
6458 ((cur >= 'A') && (cur <= 'Z')) ||
6459 ((cur >= '0') && (cur <= '9')) ||
6460 (cur == '_') || (cur == '.') ||
6461 (cur == ':') || (cur == '-')) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006462 if (len + 1 >= size) {
6463 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00006464 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00006465 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006466 xmlGenericError(xmlGenericErrorContext,
6467 "realloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006468 return(NULL);
6469 }
6470 }
6471 buf[len++] = cur;
6472 NEXT;
6473 cur=CUR;
6474 }
6475 buf[len] = 0;
6476 return(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006477}
6478
Daniel Veillard11e00581998-10-24 18:27:49 +00006479/**
6480 * xmlParseVersionInfo:
6481 * @ctxt: an XML parser context
6482 *
6483 * parse the XML version.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006484 *
6485 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
6486 *
6487 * [25] Eq ::= S? '=' S?
Daniel Veillard11e00581998-10-24 18:27:49 +00006488 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006489 * Returns the version string, e.g. "1.0"
Daniel Veillard260a68f1998-08-13 03:39:55 +00006490 */
6491
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006492xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006493xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006494 xmlChar *version = NULL;
6495 const xmlChar *q;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006496
Daniel Veillardcf461992000-03-14 18:30:20 +00006497 if ((RAW == 'v') && (NXT(1) == 'e') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006498 (NXT(2) == 'r') && (NXT(3) == 's') &&
6499 (NXT(4) == 'i') && (NXT(5) == 'o') &&
6500 (NXT(6) == 'n')) {
6501 SKIP(7);
6502 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006503 if (RAW != '=') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006504 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006505 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006506 ctxt->sax->error(ctxt->userData,
6507 "xmlParseVersionInfo : expected '='\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006508 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006509 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006510 return(NULL);
6511 }
6512 NEXT;
6513 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006514 if (RAW == '"') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006515 NEXT;
6516 q = CUR_PTR;
6517 version = xmlParseVersionNum(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006518 if (RAW != '"') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006519 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006520 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006521 ctxt->sax->error(ctxt->userData,
6522 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006523 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006524 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006525 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006526 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006527 } else if (RAW == '\''){
Daniel Veillard260a68f1998-08-13 03:39:55 +00006528 NEXT;
6529 q = CUR_PTR;
6530 version = xmlParseVersionNum(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006531 if (RAW != '\'') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006532 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006533 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006534 ctxt->sax->error(ctxt->userData,
6535 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006536 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006537 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006538 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006539 NEXT;
6540 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006541 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006542 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006543 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006544 "xmlParseVersionInfo : expected ' or \"\n");
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006545 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006546 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006547 }
6548 }
6549 return(version);
6550}
6551
Daniel Veillard11e00581998-10-24 18:27:49 +00006552/**
6553 * xmlParseEncName:
6554 * @ctxt: an XML parser context
6555 *
6556 * parse the XML encoding name
Daniel Veillard260a68f1998-08-13 03:39:55 +00006557 *
6558 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
Daniel Veillard11e00581998-10-24 18:27:49 +00006559 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006560 * Returns the encoding name value or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006561 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006562xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006563xmlParseEncName(xmlParserCtxtPtr ctxt) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006564 xmlChar *buf = NULL;
6565 int len = 0;
6566 int size = 10;
6567 xmlChar cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006568
Daniel Veillard10a2c651999-12-12 13:03:50 +00006569 cur = CUR;
6570 if (((cur >= 'a') && (cur <= 'z')) ||
6571 ((cur >= 'A') && (cur <= 'Z'))) {
6572 buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar));
6573 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006574 xmlGenericError(xmlGenericErrorContext,
6575 "malloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006576 return(NULL);
6577 }
6578
6579 buf[len++] = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006580 NEXT;
Daniel Veillard10a2c651999-12-12 13:03:50 +00006581 cur = CUR;
Daniel Veillardcf461992000-03-14 18:30:20 +00006582 while (((cur >= 'a') && (cur <= 'z')) ||
6583 ((cur >= 'A') && (cur <= 'Z')) ||
6584 ((cur >= '0') && (cur <= '9')) ||
6585 (cur == '.') || (cur == '_') ||
6586 (cur == '-')) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00006587 if (len + 1 >= size) {
6588 size *= 2;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00006589 buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
Daniel Veillard10a2c651999-12-12 13:03:50 +00006590 if (buf == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00006591 xmlGenericError(xmlGenericErrorContext,
6592 "realloc of %d byte failed\n", size);
Daniel Veillard10a2c651999-12-12 13:03:50 +00006593 return(NULL);
6594 }
6595 }
6596 buf[len++] = cur;
6597 NEXT;
6598 cur = CUR;
6599 if (cur == 0) {
6600 SHRINK;
6601 GROW;
6602 cur = CUR;
6603 }
6604 }
6605 buf[len] = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006606 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006607 ctxt->errNo = XML_ERR_ENCODING_NAME;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006608 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006609 ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006610 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006611 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006612 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00006613 return(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006614}
6615
Daniel Veillard11e00581998-10-24 18:27:49 +00006616/**
6617 * xmlParseEncodingDecl:
6618 * @ctxt: an XML parser context
6619 *
6620 * parse the XML encoding declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00006621 *
6622 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'")
Daniel Veillard11e00581998-10-24 18:27:49 +00006623 *
Daniel Veillardb1059e22000-09-16 14:02:43 +00006624 * this setups the conversion filters.
Daniel Veillard11e00581998-10-24 18:27:49 +00006625 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006626 * Returns the encoding value or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00006627 */
6628
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006629xmlChar *
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006630xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006631 xmlChar *encoding = NULL;
6632 const xmlChar *q;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006633
6634 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006635 if ((RAW == 'e') && (NXT(1) == 'n') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006636 (NXT(2) == 'c') && (NXT(3) == 'o') &&
6637 (NXT(4) == 'd') && (NXT(5) == 'i') &&
6638 (NXT(6) == 'n') && (NXT(7) == 'g')) {
6639 SKIP(8);
6640 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006641 if (RAW != '=') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006642 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006643 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006644 ctxt->sax->error(ctxt->userData,
6645 "xmlParseEncodingDecl : expected '='\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006646 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006647 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006648 return(NULL);
6649 }
6650 NEXT;
6651 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006652 if (RAW == '"') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006653 NEXT;
6654 q = CUR_PTR;
6655 encoding = xmlParseEncName(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006656 if (RAW != '"') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006657 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006658 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006659 ctxt->sax->error(ctxt->userData,
6660 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006661 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006662 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006663 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006664 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006665 } else if (RAW == '\''){
Daniel Veillard260a68f1998-08-13 03:39:55 +00006666 NEXT;
6667 q = CUR_PTR;
6668 encoding = xmlParseEncName(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00006669 if (RAW != '\'') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006670 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006671 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006672 ctxt->sax->error(ctxt->userData,
6673 "String not closed\n%.50s\n", q);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006674 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006675 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006676 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006677 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006678 } else if (RAW == '"'){
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006679 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006680 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006681 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006682 "xmlParseEncodingDecl : expected ' or \"\n");
6683 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006684 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006685 }
Daniel Veillard496a1cf2000-05-03 14:20:55 +00006686 if (encoding != NULL) {
6687 xmlCharEncoding enc;
6688 xmlCharEncodingHandlerPtr handler;
6689
6690 if (ctxt->input->encoding != NULL)
6691 xmlFree((xmlChar *) ctxt->input->encoding);
6692 ctxt->input->encoding = encoding;
6693
6694 enc = xmlParseCharEncoding((const char *) encoding);
6695 /*
6696 * registered set of known encodings
6697 */
6698 if (enc != XML_CHAR_ENCODING_ERROR) {
6699 xmlSwitchEncoding(ctxt, enc);
6700 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
6701 xmlFree(encoding);
6702 return(NULL);
6703 }
6704 } else {
6705 /*
6706 * fallback for unknown encodings
6707 */
6708 handler = xmlFindCharEncodingHandler((const char *) encoding);
6709 if (handler != NULL) {
6710 xmlSwitchToEncoding(ctxt, handler);
6711 } else {
6712 ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00006713 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
6714 ctxt->sax->error(ctxt->userData,
6715 "Unsupported encoding %s\n", encoding);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00006716 return(NULL);
6717 }
6718 }
6719 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006720 }
6721 return(encoding);
6722}
6723
Daniel Veillard11e00581998-10-24 18:27:49 +00006724/**
6725 * xmlParseSDDecl:
6726 * @ctxt: an XML parser context
6727 *
6728 * parse the XML standalone declaration
Daniel Veillard260a68f1998-08-13 03:39:55 +00006729 *
6730 * [32] SDDecl ::= S 'standalone' Eq
6731 * (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
Daniel Veillard1e346af1999-02-22 10:33:01 +00006732 *
Daniel Veillardb05deb71999-08-10 19:04:08 +00006733 * [ VC: Standalone Document Declaration ]
6734 * TODO The standalone document declaration must have the value "no"
6735 * if any external markup declarations contain declarations of:
6736 * - attributes with default values, if elements to which these
6737 * attributes apply appear in the document without specifications
6738 * of values for these attributes, or
6739 * - entities (other than amp, lt, gt, apos, quot), if references
6740 * to those entities appear in the document, or
6741 * - attributes with values subject to normalization, where the
6742 * attribute appears in the document with a value which will change
6743 * as a result of normalization, or
6744 * - element types with element content, if white space occurs directly
6745 * within any instance of those types.
6746 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006747 * Returns 1 if standalone, 0 otherwise
Daniel Veillard260a68f1998-08-13 03:39:55 +00006748 */
6749
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006750int
6751xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006752 int standalone = -1;
6753
6754 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006755 if ((RAW == 's') && (NXT(1) == 't') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006756 (NXT(2) == 'a') && (NXT(3) == 'n') &&
6757 (NXT(4) == 'd') && (NXT(5) == 'a') &&
6758 (NXT(6) == 'l') && (NXT(7) == 'o') &&
6759 (NXT(8) == 'n') && (NXT(9) == 'e')) {
6760 SKIP(10);
Daniel Veillard011b63c1999-06-02 17:44:04 +00006761 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006762 if (RAW != '=') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006763 ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006764 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006765 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006766 "XML standalone declaration : expected '='\n");
6767 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006768 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006769 return(standalone);
6770 }
6771 NEXT;
6772 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006773 if (RAW == '\''){
Daniel Veillard260a68f1998-08-13 03:39:55 +00006774 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006775 if ((RAW == 'n') && (NXT(1) == 'o')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006776 standalone = 0;
6777 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00006778 } else if ((RAW == 'y') && (NXT(1) == 'e') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006779 (NXT(2) == 's')) {
6780 standalone = 1;
6781 SKIP(3);
6782 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006783 ctxt->errNo = XML_ERR_STANDALONE_VALUE;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006784 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006785 ctxt->sax->error(ctxt->userData,
6786 "standalone accepts only 'yes' or 'no'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006787 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006788 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006789 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006790 if (RAW != '\'') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006791 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006792 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006793 ctxt->sax->error(ctxt->userData, "String not closed\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006794 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006795 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006796 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006797 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006798 } else if (RAW == '"'){
Daniel Veillard260a68f1998-08-13 03:39:55 +00006799 NEXT;
Daniel Veillardcf461992000-03-14 18:30:20 +00006800 if ((RAW == 'n') && (NXT(1) == 'o')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006801 standalone = 0;
6802 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00006803 } else if ((RAW == 'y') && (NXT(1) == 'e') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006804 (NXT(2) == 's')) {
6805 standalone = 1;
6806 SKIP(3);
6807 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006808 ctxt->errNo = XML_ERR_STANDALONE_VALUE;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006809 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006810 ctxt->sax->error(ctxt->userData,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006811 "standalone accepts only 'yes' or 'no'\n");
6812 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006813 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006814 }
Daniel Veillardcf461992000-03-14 18:30:20 +00006815 if (RAW != '"') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006816 ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006817 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006818 ctxt->sax->error(ctxt->userData, "String not closed\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006819 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006820 ctxt->disableSAX = 1;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006821 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00006822 NEXT;
6823 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006824 ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006825 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006826 ctxt->sax->error(ctxt->userData,
6827 "Standalone value not found\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006828 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006829 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006830 }
6831 }
6832 return(standalone);
6833}
6834
Daniel Veillard11e00581998-10-24 18:27:49 +00006835/**
6836 * xmlParseXMLDecl:
6837 * @ctxt: an XML parser context
6838 *
6839 * parse an XML declaration header
Daniel Veillard260a68f1998-08-13 03:39:55 +00006840 *
6841 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
6842 */
6843
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006844void
6845xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00006846 xmlChar *version;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006847
6848 /*
6849 * We know that '<?xml' is here.
6850 */
6851 SKIP(5);
6852
Daniel Veillardcf461992000-03-14 18:30:20 +00006853 if (!IS_BLANK(RAW)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006854 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006855 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006856 ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006857 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006858 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006859 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006860 SKIP_BLANKS;
6861
6862 /*
6863 * We should have the VersionInfo here.
6864 */
6865 version = xmlParseVersionInfo(ctxt);
6866 if (version == NULL)
6867 version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillard517752b1999-04-05 12:20:10 +00006868 ctxt->version = xmlStrdup(version);
Daniel Veillard6454aec1999-09-02 22:04:43 +00006869 xmlFree(version);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006870
6871 /*
6872 * We may have the encoding declaration
6873 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006874 if (!IS_BLANK(RAW)) {
6875 if ((RAW == '?') && (NXT(1) == '>')) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006876 SKIP(2);
6877 return;
6878 }
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006879 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006880 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006881 ctxt->sax->error(ctxt->userData, "Blank needed here\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006882 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006883 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006884 }
Daniel Veillard496a1cf2000-05-03 14:20:55 +00006885 xmlParseEncodingDecl(ctxt);
6886 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
6887 /*
6888 * The XML REC instructs us to stop parsing right here
6889 */
6890 return;
6891 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00006892
6893 /*
6894 * We may have the standalone status.
6895 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006896 if ((ctxt->input->encoding != NULL) && (!IS_BLANK(RAW))) {
6897 if ((RAW == '?') && (NXT(1) == '>')) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006898 SKIP(2);
6899 return;
6900 }
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006901 ctxt->errNo = XML_ERR_SPACE_REQUIRED;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006902 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00006903 ctxt->sax->error(ctxt->userData, "Blank needed here\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006904 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006905 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006906 }
6907 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006908 ctxt->input->standalone = xmlParseSDDecl(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006909
6910 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00006911 if ((RAW == '?') && (NXT(1) == '>')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006912 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00006913 } else if (RAW == '>') {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006914 /* Deprecated old WD ... */
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006915 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006916 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006917 ctxt->sax->error(ctxt->userData,
6918 "XML declaration must end-up with '?>'\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006919 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006920 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006921 NEXT;
6922 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00006923 ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
Daniel Veillarde3bffb91998-11-08 14:40:56 +00006924 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard7f7d1111999-09-22 09:46:25 +00006925 ctxt->sax->error(ctxt->userData,
6926 "parsing XML declaration: '?>' expected\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006927 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00006928 ctxt->disableSAX = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00006929 MOVETO_ENDTAG(CUR_PTR);
6930 NEXT;
6931 }
6932}
6933
Daniel Veillard11e00581998-10-24 18:27:49 +00006934/**
6935 * xmlParseMisc:
6936 * @ctxt: an XML parser context
6937 *
6938 * parse an XML Misc* optionnal field.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006939 *
6940 * [27] Misc ::= Comment | PI | S
6941 */
6942
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006943void
6944xmlParseMisc(xmlParserCtxtPtr ctxt) {
Daniel Veillardcf461992000-03-14 18:30:20 +00006945 while (((RAW == '<') && (NXT(1) == '?')) ||
6946 ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00006947 (NXT(2) == '-') && (NXT(3) == '-')) ||
6948 IS_BLANK(CUR)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00006949 if ((RAW == '<') && (NXT(1) == '?')) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00006950 xmlParsePI(ctxt);
6951 } else if (IS_BLANK(CUR)) {
6952 NEXT;
6953 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00006954 xmlParseComment(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006955 }
6956}
6957
Daniel Veillard11e00581998-10-24 18:27:49 +00006958/**
Daniel Veillardcf461992000-03-14 18:30:20 +00006959 * xmlParseDocument:
Daniel Veillard11e00581998-10-24 18:27:49 +00006960 * @ctxt: an XML parser context
6961 *
6962 * parse an XML document (and build a tree if using the standard SAX
6963 * interface).
Daniel Veillard260a68f1998-08-13 03:39:55 +00006964 *
6965 * [1] document ::= prolog element Misc*
6966 *
6967 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
Daniel Veillard11e00581998-10-24 18:27:49 +00006968 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00006969 * Returns 0, -1 in case of error. the parser context is augmented
Daniel Veillard11e00581998-10-24 18:27:49 +00006970 * as a result of the parsing.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006971 */
6972
Daniel Veillard0ba4d531998-11-01 19:34:31 +00006973int
6974xmlParseDocument(xmlParserCtxtPtr ctxt) {
Daniel Veillardcf461992000-03-14 18:30:20 +00006975 xmlChar start[4];
6976 xmlCharEncoding enc;
6977
Daniel Veillardbc765302000-10-01 18:23:35 +00006978 xmlInitParser();
Daniel Veillard260a68f1998-08-13 03:39:55 +00006979
Daniel Veillarde2d034d1999-07-27 19:52:06 +00006980 GROW;
6981
Daniel Veillard260a68f1998-08-13 03:39:55 +00006982 /*
6983 * SAX: beginning of the document processing.
6984 */
Daniel Veillard517752b1999-04-05 12:20:10 +00006985 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
Daniel Veillard27d88741999-05-29 11:51:49 +00006986 ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
Daniel Veillard260a68f1998-08-13 03:39:55 +00006987
Daniel Veillardcf461992000-03-14 18:30:20 +00006988 /*
6989 * Get the 4 first bytes and decode the charset
6990 * if enc != XML_CHAR_ENCODING_NONE
6991 * plug some encoding conversion routines.
Daniel Veillard260a68f1998-08-13 03:39:55 +00006992 */
Daniel Veillardcf461992000-03-14 18:30:20 +00006993 start[0] = RAW;
6994 start[1] = NXT(1);
6995 start[2] = NXT(2);
6996 start[3] = NXT(3);
6997 enc = xmlDetectCharEncoding(start, 4);
6998 if (enc != XML_CHAR_ENCODING_NONE) {
6999 xmlSwitchEncoding(ctxt, enc);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007000 }
7001
Daniel Veillardcf461992000-03-14 18:30:20 +00007002
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007003 if (CUR == 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007004 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007005 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00007006 ctxt->sax->error(ctxt->userData, "Document is empty\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007007 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007008 ctxt->disableSAX = 1;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007009 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00007010
7011 /*
7012 * Check for the XMLDecl in the Prolog.
7013 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00007014 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00007015 if ((RAW == '<') && (NXT(1) == '?') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00007016 (NXT(2) == 'x') && (NXT(3) == 'm') &&
Daniel Veillard686d6b62000-01-03 11:08:02 +00007017 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
Daniel Veillard496a1cf2000-05-03 14:20:55 +00007018
7019 /*
7020 * Note that we will switch encoding on the fly.
7021 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00007022 xmlParseXMLDecl(ctxt);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00007023 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7024 /*
7025 * The XML REC instructs us to stop parsing right here
7026 */
7027 return(-1);
7028 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007029 ctxt->standalone = ctxt->input->standalone;
Daniel Veillard260a68f1998-08-13 03:39:55 +00007030 SKIP_BLANKS;
Daniel Veillard260a68f1998-08-13 03:39:55 +00007031 } else {
Daniel Veillard517752b1999-04-05 12:20:10 +00007032 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillard260a68f1998-08-13 03:39:55 +00007033 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007034 if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
Daniel Veillard27d88741999-05-29 11:51:49 +00007035 ctxt->sax->startDocument(ctxt->userData);
Daniel Veillard260a68f1998-08-13 03:39:55 +00007036
7037 /*
7038 * The Misc part of the Prolog
7039 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00007040 GROW;
Daniel Veillard260a68f1998-08-13 03:39:55 +00007041 xmlParseMisc(ctxt);
7042
7043 /*
7044 * Then possibly doc type declaration(s) and more Misc
7045 * (doctypedecl Misc*)?
7046 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00007047 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00007048 if ((RAW == '<') && (NXT(1) == '!') &&
Daniel Veillard260a68f1998-08-13 03:39:55 +00007049 (NXT(2) == 'D') && (NXT(3) == 'O') &&
7050 (NXT(4) == 'C') && (NXT(5) == 'T') &&
7051 (NXT(6) == 'Y') && (NXT(7) == 'P') &&
7052 (NXT(8) == 'E')) {
Daniel Veillardcf461992000-03-14 18:30:20 +00007053
7054 ctxt->inSubset = 1;
Daniel Veillard260a68f1998-08-13 03:39:55 +00007055 xmlParseDocTypeDecl(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00007056 if (RAW == '[') {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007057 ctxt->instate = XML_PARSER_DTD;
7058 xmlParseInternalSubset(ctxt);
7059 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007060
7061 /*
7062 * Create and update the external subset.
7063 */
7064 ctxt->inSubset = 2;
7065 if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
7066 (!ctxt->disableSAX))
7067 ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
7068 ctxt->extSubSystem, ctxt->extSubURI);
7069 ctxt->inSubset = 0;
7070
7071
Daniel Veillardb05deb71999-08-10 19:04:08 +00007072 ctxt->instate = XML_PARSER_PROLOG;
Daniel Veillard260a68f1998-08-13 03:39:55 +00007073 xmlParseMisc(ctxt);
7074 }
7075
7076 /*
7077 * Time to start parsing the tree itself
7078 */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00007079 GROW;
Daniel Veillardcf461992000-03-14 18:30:20 +00007080 if (RAW != '<') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007081 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007082 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
Daniel Veillard27d88741999-05-29 11:51:49 +00007083 ctxt->sax->error(ctxt->userData,
Daniel Veillardcf461992000-03-14 18:30:20 +00007084 "Start tag expected, '<' not found\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007085 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007086 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007087 ctxt->instate = XML_PARSER_EOF;
7088 } else {
7089 ctxt->instate = XML_PARSER_CONTENT;
7090 xmlParseElement(ctxt);
7091 ctxt->instate = XML_PARSER_EPILOG;
7092
7093
7094 /*
7095 * The Misc part at the end
7096 */
7097 xmlParseMisc(ctxt);
7098
Daniel Veillardcf461992000-03-14 18:30:20 +00007099 if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007100 ctxt->errNo = XML_ERR_DOCUMENT_END;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007101 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7102 ctxt->sax->error(ctxt->userData,
7103 "Extra content at the end of the document\n");
7104 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007105 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007106 }
7107 ctxt->instate = XML_PARSER_EOF;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007108 }
7109
Daniel Veillard260a68f1998-08-13 03:39:55 +00007110 /*
7111 * SAX: end of the document processing.
7112 */
Daniel Veillardcf461992000-03-14 18:30:20 +00007113 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
7114 (!ctxt->disableSAX))
Daniel Veillard27d88741999-05-29 11:51:49 +00007115 ctxt->sax->endDocument(ctxt->userData);
Daniel Veillardcf461992000-03-14 18:30:20 +00007116
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007117 if (! ctxt->wellFormed) return(-1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00007118 return(0);
7119}
7120
Daniel Veillardb1059e22000-09-16 14:02:43 +00007121/**
7122 * xmlParseExtParsedEnt:
7123 * @ctxt: an XML parser context
7124 *
7125 * parse a genreral parsed entity
7126 * An external general parsed entity is well-formed if it matches the
7127 * production labeled extParsedEnt.
7128 *
7129 * [78] extParsedEnt ::= TextDecl? content
7130 *
7131 * Returns 0, -1 in case of error. the parser context is augmented
7132 * as a result of the parsing.
7133 */
7134
7135int
7136xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
7137 xmlChar start[4];
7138 xmlCharEncoding enc;
7139
7140 xmlDefaultSAXHandlerInit();
7141
7142 GROW;
7143
7144 /*
7145 * SAX: beginning of the document processing.
7146 */
7147 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
7148 ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
7149
7150 /*
7151 * Get the 4 first bytes and decode the charset
7152 * if enc != XML_CHAR_ENCODING_NONE
7153 * plug some encoding conversion routines.
7154 */
7155 start[0] = RAW;
7156 start[1] = NXT(1);
7157 start[2] = NXT(2);
7158 start[3] = NXT(3);
7159 enc = xmlDetectCharEncoding(start, 4);
7160 if (enc != XML_CHAR_ENCODING_NONE) {
7161 xmlSwitchEncoding(ctxt, enc);
7162 }
7163
7164
7165 if (CUR == 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007166 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillardb1059e22000-09-16 14:02:43 +00007167 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7168 ctxt->sax->error(ctxt->userData, "Document is empty\n");
Daniel Veillardb1059e22000-09-16 14:02:43 +00007169 ctxt->wellFormed = 0;
7170 ctxt->disableSAX = 1;
7171 }
7172
7173 /*
7174 * Check for the XMLDecl in the Prolog.
7175 */
7176 GROW;
7177 if ((RAW == '<') && (NXT(1) == '?') &&
7178 (NXT(2) == 'x') && (NXT(3) == 'm') &&
7179 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
7180
7181 /*
7182 * Note that we will switch encoding on the fly.
7183 */
7184 xmlParseXMLDecl(ctxt);
7185 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7186 /*
7187 * The XML REC instructs us to stop parsing right here
7188 */
7189 return(-1);
7190 }
7191 SKIP_BLANKS;
7192 } else {
7193 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
7194 }
7195 if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
7196 ctxt->sax->startDocument(ctxt->userData);
7197
7198 /*
7199 * Doing validity checking on chunk doesn't make sense
7200 */
7201 ctxt->instate = XML_PARSER_CONTENT;
7202 ctxt->validate = 0;
7203 ctxt->depth = 0;
7204
7205 xmlParseContent(ctxt);
7206
7207 if ((RAW == '<') && (NXT(1) == '/')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007208 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillardb1059e22000-09-16 14:02:43 +00007209 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7210 ctxt->sax->error(ctxt->userData,
7211 "chunk is not well balanced\n");
7212 ctxt->wellFormed = 0;
7213 ctxt->disableSAX = 1;
Daniel Veillardb1059e22000-09-16 14:02:43 +00007214 } else if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007215 ctxt->errNo = XML_ERR_EXTRA_CONTENT;
Daniel Veillardb1059e22000-09-16 14:02:43 +00007216 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7217 ctxt->sax->error(ctxt->userData,
7218 "extra content at the end of well balanced chunk\n");
7219 ctxt->wellFormed = 0;
7220 ctxt->disableSAX = 1;
Daniel Veillardb1059e22000-09-16 14:02:43 +00007221 }
7222
7223 /*
7224 * SAX: end of the document processing.
7225 */
7226 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
7227 (!ctxt->disableSAX))
7228 ctxt->sax->endDocument(ctxt->userData);
7229
7230 if (! ctxt->wellFormed) return(-1);
7231 return(0);
7232}
7233
Daniel Veillardb05deb71999-08-10 19:04:08 +00007234/************************************************************************
7235 * *
Daniel Veillard7f858501999-11-17 17:32:38 +00007236 * Progressive parsing interfaces *
7237 * *
7238 ************************************************************************/
7239
7240/**
7241 * xmlParseLookupSequence:
7242 * @ctxt: an XML parser context
7243 * @first: the first char to lookup
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007244 * @next: the next char to lookup or zero
7245 * @third: the next char to lookup or zero
Daniel Veillard7f858501999-11-17 17:32:38 +00007246 *
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007247 * Try to find if a sequence (first, next, third) or just (first next) or
7248 * (first) is available in the input stream.
7249 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
7250 * to avoid rescanning sequences of bytes, it DOES change the state of the
7251 * parser, do not use liberally.
Daniel Veillard7f858501999-11-17 17:32:38 +00007252 *
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007253 * Returns the index to the current parsing point if the full sequence
7254 * is available, -1 otherwise.
Daniel Veillard7f858501999-11-17 17:32:38 +00007255 */
7256int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007257xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
7258 xmlChar next, xmlChar third) {
7259 int base, len;
7260 xmlParserInputPtr in;
7261 const xmlChar *buf;
7262
7263 in = ctxt->input;
7264 if (in == NULL) return(-1);
7265 base = in->cur - in->base;
7266 if (base < 0) return(-1);
7267 if (ctxt->checkIndex > base)
7268 base = ctxt->checkIndex;
7269 if (in->buf == NULL) {
7270 buf = in->base;
7271 len = in->length;
7272 } else {
7273 buf = in->buf->buffer->content;
7274 len = in->buf->buffer->use;
7275 }
7276 /* take into account the sequence length */
7277 if (third) len -= 2;
7278 else if (next) len --;
7279 for (;base < len;base++) {
7280 if (buf[base] == first) {
7281 if (third != 0) {
7282 if ((buf[base + 1] != next) ||
7283 (buf[base + 2] != third)) continue;
7284 } else if (next != 0) {
7285 if (buf[base + 1] != next) continue;
7286 }
7287 ctxt->checkIndex = 0;
7288#ifdef DEBUG_PUSH
7289 if (next == 0)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007290 xmlGenericError(xmlGenericErrorContext,
7291 "PP: lookup '%c' found at %d\n",
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007292 first, base);
7293 else if (third == 0)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007294 xmlGenericError(xmlGenericErrorContext,
7295 "PP: lookup '%c%c' found at %d\n",
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007296 first, next, base);
7297 else
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007298 xmlGenericError(xmlGenericErrorContext,
7299 "PP: lookup '%c%c%c' found at %d\n",
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007300 first, next, third, base);
7301#endif
7302 return(base - (in->cur - in->base));
7303 }
7304 }
7305 ctxt->checkIndex = base;
7306#ifdef DEBUG_PUSH
7307 if (next == 0)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007308 xmlGenericError(xmlGenericErrorContext,
7309 "PP: lookup '%c' failed\n", first);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007310 else if (third == 0)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007311 xmlGenericError(xmlGenericErrorContext,
7312 "PP: lookup '%c%c' failed\n", first, next);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007313 else
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007314 xmlGenericError(xmlGenericErrorContext,
7315 "PP: lookup '%c%c%c' failed\n", first, next, third);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007316#endif
7317 return(-1);
Daniel Veillard7f858501999-11-17 17:32:38 +00007318}
7319
7320/**
Daniel Veillard71b656e2000-01-05 14:46:17 +00007321 * xmlParseTryOrFinish:
Daniel Veillard7f858501999-11-17 17:32:38 +00007322 * @ctxt: an XML parser context
Daniel Veillard71b656e2000-01-05 14:46:17 +00007323 * @terminate: last chunk indicator
Daniel Veillard7f858501999-11-17 17:32:38 +00007324 *
7325 * Try to progress on parsing
7326 *
7327 * Returns zero if no parsing was possible
7328 */
7329int
Daniel Veillard71b656e2000-01-05 14:46:17 +00007330xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
Daniel Veillard7f858501999-11-17 17:32:38 +00007331 int ret = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007332 int avail;
7333 xmlChar cur, next;
7334
7335#ifdef DEBUG_PUSH
7336 switch (ctxt->instate) {
7337 case XML_PARSER_EOF:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007338 xmlGenericError(xmlGenericErrorContext,
7339 "PP: try EOF\n"); break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007340 case XML_PARSER_START:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007341 xmlGenericError(xmlGenericErrorContext,
7342 "PP: try START\n"); break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007343 case XML_PARSER_MISC:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007344 xmlGenericError(xmlGenericErrorContext,
7345 "PP: try MISC\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007346 case XML_PARSER_COMMENT:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007347 xmlGenericError(xmlGenericErrorContext,
7348 "PP: try COMMENT\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007349 case XML_PARSER_PROLOG:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007350 xmlGenericError(xmlGenericErrorContext,
7351 "PP: try PROLOG\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007352 case XML_PARSER_START_TAG:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007353 xmlGenericError(xmlGenericErrorContext,
7354 "PP: try START_TAG\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007355 case XML_PARSER_CONTENT:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007356 xmlGenericError(xmlGenericErrorContext,
7357 "PP: try CONTENT\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007358 case XML_PARSER_CDATA_SECTION:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007359 xmlGenericError(xmlGenericErrorContext,
7360 "PP: try CDATA_SECTION\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007361 case XML_PARSER_END_TAG:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007362 xmlGenericError(xmlGenericErrorContext,
7363 "PP: try END_TAG\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007364 case XML_PARSER_ENTITY_DECL:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007365 xmlGenericError(xmlGenericErrorContext,
7366 "PP: try ENTITY_DECL\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007367 case XML_PARSER_ENTITY_VALUE:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007368 xmlGenericError(xmlGenericErrorContext,
7369 "PP: try ENTITY_VALUE\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007370 case XML_PARSER_ATTRIBUTE_VALUE:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007371 xmlGenericError(xmlGenericErrorContext,
7372 "PP: try ATTRIBUTE_VALUE\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007373 case XML_PARSER_DTD:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007374 xmlGenericError(xmlGenericErrorContext,
7375 "PP: try DTD\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007376 case XML_PARSER_EPILOG:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007377 xmlGenericError(xmlGenericErrorContext,
7378 "PP: try EPILOG\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007379 case XML_PARSER_PI:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007380 xmlGenericError(xmlGenericErrorContext,
7381 "PP: try PI\n");break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007382 }
7383#endif
Daniel Veillard7f858501999-11-17 17:32:38 +00007384
7385 while (1) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007386 /*
7387 * Pop-up of finished entities.
7388 */
Daniel Veillardcf461992000-03-14 18:30:20 +00007389 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007390 xmlPopInput(ctxt);
7391
Daniel Veillardcf461992000-03-14 18:30:20 +00007392 if (ctxt->input ==NULL) break;
7393 if (ctxt->input->buf == NULL)
7394 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007395 else
Daniel Veillardcf461992000-03-14 18:30:20 +00007396 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007397 if (avail < 1)
7398 goto done;
Daniel Veillard7f858501999-11-17 17:32:38 +00007399 switch (ctxt->instate) {
7400 case XML_PARSER_EOF:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007401 /*
7402 * Document parsing is done !
7403 */
7404 goto done;
7405 case XML_PARSER_START:
7406 /*
7407 * Very first chars read from the document flow.
7408 */
Daniel Veillardcf461992000-03-14 18:30:20 +00007409 cur = ctxt->input->cur[0];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007410 if (IS_BLANK(cur)) {
7411 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
7412 ctxt->sax->setDocumentLocator(ctxt->userData,
7413 &xmlDefaultSAXLocator);
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007414 ctxt->errNo = XML_ERR_DOCUMENT_START;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007415 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7416 ctxt->sax->error(ctxt->userData,
7417 "Extra spaces at the beginning of the document are not allowed\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007418 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007419 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007420 SKIP_BLANKS;
7421 ret++;
Daniel Veillardcf461992000-03-14 18:30:20 +00007422 if (ctxt->input->buf == NULL)
7423 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007424 else
Daniel Veillardcf461992000-03-14 18:30:20 +00007425 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007426 }
7427 if (avail < 2)
7428 goto done;
7429
Daniel Veillardcf461992000-03-14 18:30:20 +00007430 cur = ctxt->input->cur[0];
7431 next = ctxt->input->cur[1];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007432 if (cur == 0) {
7433 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
7434 ctxt->sax->setDocumentLocator(ctxt->userData,
7435 &xmlDefaultSAXLocator);
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007436 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007437 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7438 ctxt->sax->error(ctxt->userData, "Document is empty\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007439 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007440 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007441 ctxt->instate = XML_PARSER_EOF;
7442#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007443 xmlGenericError(xmlGenericErrorContext,
7444 "PP: entering EOF\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007445#endif
7446 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
7447 ctxt->sax->endDocument(ctxt->userData);
7448 goto done;
7449 }
7450 if ((cur == '<') && (next == '?')) {
7451 /* PI or XML decl */
7452 if (avail < 5) return(ret);
Daniel Veillard71b656e2000-01-05 14:46:17 +00007453 if ((!terminate) &&
7454 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007455 return(ret);
7456 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
7457 ctxt->sax->setDocumentLocator(ctxt->userData,
7458 &xmlDefaultSAXLocator);
Daniel Veillardcf461992000-03-14 18:30:20 +00007459 if ((ctxt->input->cur[2] == 'x') &&
7460 (ctxt->input->cur[3] == 'm') &&
7461 (ctxt->input->cur[4] == 'l') &&
7462 (IS_BLANK(ctxt->input->cur[5]))) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007463 ret += 5;
7464#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007465 xmlGenericError(xmlGenericErrorContext,
7466 "PP: Parsing XML Decl\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007467#endif
7468 xmlParseXMLDecl(ctxt);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00007469 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7470 /*
7471 * The XML REC instructs us to stop parsing right
7472 * here
7473 */
7474 ctxt->instate = XML_PARSER_EOF;
7475 return(0);
7476 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007477 ctxt->standalone = ctxt->input->standalone;
7478 if ((ctxt->encoding == NULL) &&
7479 (ctxt->input->encoding != NULL))
7480 ctxt->encoding = xmlStrdup(ctxt->input->encoding);
7481 if ((ctxt->sax) && (ctxt->sax->startDocument) &&
7482 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007483 ctxt->sax->startDocument(ctxt->userData);
7484 ctxt->instate = XML_PARSER_MISC;
7485#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007486 xmlGenericError(xmlGenericErrorContext,
7487 "PP: entering MISC\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007488#endif
7489 } else {
7490 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillardcf461992000-03-14 18:30:20 +00007491 if ((ctxt->sax) && (ctxt->sax->startDocument) &&
7492 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007493 ctxt->sax->startDocument(ctxt->userData);
7494 ctxt->instate = XML_PARSER_MISC;
7495#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007496 xmlGenericError(xmlGenericErrorContext,
7497 "PP: entering MISC\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007498#endif
7499 }
7500 } else {
7501 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
7502 ctxt->sax->setDocumentLocator(ctxt->userData,
7503 &xmlDefaultSAXLocator);
7504 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
Daniel Veillardcf461992000-03-14 18:30:20 +00007505 if ((ctxt->sax) && (ctxt->sax->startDocument) &&
7506 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007507 ctxt->sax->startDocument(ctxt->userData);
7508 ctxt->instate = XML_PARSER_MISC;
7509#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007510 xmlGenericError(xmlGenericErrorContext,
7511 "PP: entering MISC\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007512#endif
7513 }
7514 break;
7515 case XML_PARSER_MISC:
7516 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00007517 if (ctxt->input->buf == NULL)
7518 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007519 else
Daniel Veillardcf461992000-03-14 18:30:20 +00007520 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007521 if (avail < 2)
7522 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007523 cur = ctxt->input->cur[0];
7524 next = ctxt->input->cur[1];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007525 if ((cur == '<') && (next == '?')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007526 if ((!terminate) &&
7527 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007528 goto done;
7529#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007530 xmlGenericError(xmlGenericErrorContext,
7531 "PP: Parsing PI\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007532#endif
7533 xmlParsePI(ctxt);
7534 } else if ((cur == '<') && (next == '!') &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007535 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007536 if ((!terminate) &&
7537 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007538 goto done;
7539#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007540 xmlGenericError(xmlGenericErrorContext,
7541 "PP: Parsing Comment\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007542#endif
7543 xmlParseComment(ctxt);
7544 ctxt->instate = XML_PARSER_MISC;
7545 } else if ((cur == '<') && (next == '!') &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007546 (ctxt->input->cur[2] == 'D') && (ctxt->input->cur[3] == 'O') &&
7547 (ctxt->input->cur[4] == 'C') && (ctxt->input->cur[5] == 'T') &&
7548 (ctxt->input->cur[6] == 'Y') && (ctxt->input->cur[7] == 'P') &&
7549 (ctxt->input->cur[8] == 'E')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007550 if ((!terminate) &&
7551 (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007552 goto done;
7553#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007554 xmlGenericError(xmlGenericErrorContext,
7555 "PP: Parsing internal subset\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007556#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00007557 ctxt->inSubset = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007558 xmlParseDocTypeDecl(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00007559 if (RAW == '[') {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007560 ctxt->instate = XML_PARSER_DTD;
7561#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007562 xmlGenericError(xmlGenericErrorContext,
7563 "PP: entering DTD\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007564#endif
7565 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00007566 /*
7567 * Create and update the external subset.
7568 */
7569 ctxt->inSubset = 2;
7570 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
7571 (ctxt->sax->externalSubset != NULL))
7572 ctxt->sax->externalSubset(ctxt->userData,
7573 ctxt->intSubName, ctxt->extSubSystem,
7574 ctxt->extSubURI);
7575 ctxt->inSubset = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007576 ctxt->instate = XML_PARSER_PROLOG;
7577#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007578 xmlGenericError(xmlGenericErrorContext,
7579 "PP: entering PROLOG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007580#endif
7581 }
7582 } else if ((cur == '<') && (next == '!') &&
7583 (avail < 9)) {
7584 goto done;
7585 } else {
7586 ctxt->instate = XML_PARSER_START_TAG;
7587#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007588 xmlGenericError(xmlGenericErrorContext,
7589 "PP: entering START_TAG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007590#endif
7591 }
7592 break;
Daniel Veillard7f858501999-11-17 17:32:38 +00007593 case XML_PARSER_PROLOG:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007594 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00007595 if (ctxt->input->buf == NULL)
7596 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007597 else
Daniel Veillardcf461992000-03-14 18:30:20 +00007598 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007599 if (avail < 2)
7600 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007601 cur = ctxt->input->cur[0];
7602 next = ctxt->input->cur[1];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007603 if ((cur == '<') && (next == '?')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007604 if ((!terminate) &&
7605 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007606 goto done;
7607#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007608 xmlGenericError(xmlGenericErrorContext,
7609 "PP: Parsing PI\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007610#endif
7611 xmlParsePI(ctxt);
7612 } else if ((cur == '<') && (next == '!') &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007613 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007614 if ((!terminate) &&
7615 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007616 goto done;
7617#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007618 xmlGenericError(xmlGenericErrorContext,
7619 "PP: Parsing Comment\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007620#endif
7621 xmlParseComment(ctxt);
7622 ctxt->instate = XML_PARSER_PROLOG;
7623 } else if ((cur == '<') && (next == '!') &&
7624 (avail < 4)) {
7625 goto done;
7626 } else {
7627 ctxt->instate = XML_PARSER_START_TAG;
7628#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007629 xmlGenericError(xmlGenericErrorContext,
7630 "PP: entering START_TAG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007631#endif
7632 }
7633 break;
Daniel Veillard7f858501999-11-17 17:32:38 +00007634 case XML_PARSER_EPILOG:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007635 SKIP_BLANKS;
Daniel Veillardcf461992000-03-14 18:30:20 +00007636 if (ctxt->input->buf == NULL)
7637 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007638 else
Daniel Veillardcf461992000-03-14 18:30:20 +00007639 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007640 if (avail < 2)
7641 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007642 cur = ctxt->input->cur[0];
7643 next = ctxt->input->cur[1];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007644 if ((cur == '<') && (next == '?')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007645 if ((!terminate) &&
7646 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007647 goto done;
7648#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007649 xmlGenericError(xmlGenericErrorContext,
7650 "PP: Parsing PI\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007651#endif
7652 xmlParsePI(ctxt);
7653 ctxt->instate = XML_PARSER_EPILOG;
7654 } else if ((cur == '<') && (next == '!') &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007655 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007656 if ((!terminate) &&
7657 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007658 goto done;
7659#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007660 xmlGenericError(xmlGenericErrorContext,
7661 "PP: Parsing Comment\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007662#endif
7663 xmlParseComment(ctxt);
7664 ctxt->instate = XML_PARSER_EPILOG;
7665 } else if ((cur == '<') && (next == '!') &&
7666 (avail < 4)) {
7667 goto done;
7668 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007669 ctxt->errNo = XML_ERR_DOCUMENT_END;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007670 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7671 ctxt->sax->error(ctxt->userData,
7672 "Extra content at the end of the document\n");
7673 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007674 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007675 ctxt->instate = XML_PARSER_EOF;
7676#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007677 xmlGenericError(xmlGenericErrorContext,
7678 "PP: entering EOF\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007679#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00007680 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
7681 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007682 ctxt->sax->endDocument(ctxt->userData);
7683 goto done;
7684 }
7685 break;
7686 case XML_PARSER_START_TAG: {
7687 xmlChar *name, *oldname;
7688
Daniel Veillardcf461992000-03-14 18:30:20 +00007689 if ((avail < 2) && (ctxt->inputNr == 1))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007690 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007691 cur = ctxt->input->cur[0];
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007692 if (cur != '<') {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007693 ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007694 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7695 ctxt->sax->error(ctxt->userData,
7696 "Start tag expect, '<' not found\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007697 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007698 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007699 ctxt->instate = XML_PARSER_EOF;
7700#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007701 xmlGenericError(xmlGenericErrorContext,
7702 "PP: entering EOF\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007703#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00007704 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
7705 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007706 ctxt->sax->endDocument(ctxt->userData);
7707 goto done;
7708 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00007709 if ((!terminate) &&
7710 (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007711 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007712 if (ctxt->spaceNr == 0)
7713 spacePush(ctxt, -1);
7714 else
7715 spacePush(ctxt, *ctxt->space);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007716 name = xmlParseStartTag(ctxt);
7717 if (name == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00007718 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007719 ctxt->instate = XML_PARSER_EOF;
7720#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007721 xmlGenericError(xmlGenericErrorContext,
7722 "PP: entering EOF\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007723#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00007724 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
7725 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007726 ctxt->sax->endDocument(ctxt->userData);
7727 goto done;
7728 }
7729 namePush(ctxt, xmlStrdup(name));
7730
7731 /*
7732 * [ VC: Root Element Type ]
7733 * The Name in the document type declaration must match
7734 * the element type of the root element.
7735 */
7736 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007737 ctxt->node && (ctxt->node == ctxt->myDoc->children))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007738 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
7739
7740 /*
7741 * Check for an Empty Element.
7742 */
Daniel Veillardcf461992000-03-14 18:30:20 +00007743 if ((RAW == '/') && (NXT(1) == '>')) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007744 SKIP(2);
Daniel Veillardcf461992000-03-14 18:30:20 +00007745 if ((ctxt->sax != NULL) &&
7746 (ctxt->sax->endElement != NULL) && (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007747 ctxt->sax->endElement(ctxt->userData, name);
7748 xmlFree(name);
7749 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00007750 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007751 if (oldname != NULL) {
7752#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007753 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007754#endif
7755 xmlFree(oldname);
7756 }
7757 if (ctxt->name == NULL) {
7758 ctxt->instate = XML_PARSER_EPILOG;
7759#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007760 xmlGenericError(xmlGenericErrorContext,
7761 "PP: entering EPILOG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007762#endif
7763 } else {
7764 ctxt->instate = XML_PARSER_CONTENT;
7765#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007766 xmlGenericError(xmlGenericErrorContext,
7767 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007768#endif
7769 }
7770 break;
7771 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007772 if (RAW == '>') {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007773 NEXT;
7774 } else {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007775 ctxt->errNo = XML_ERR_GT_REQUIRED;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007776 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7777 ctxt->sax->error(ctxt->userData,
7778 "Couldn't find end of Start Tag %s\n",
7779 name);
7780 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00007781 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007782
7783 /*
7784 * end of parsing of this node.
7785 */
7786 nodePop(ctxt);
7787 oldname = namePop(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00007788 spacePop(ctxt);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007789 if (oldname != NULL) {
7790#ifdef DEBUG_STACK
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007791 xmlGenericError(xmlGenericErrorContext,"Close: popped %s\n", oldname);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007792#endif
7793 xmlFree(oldname);
7794 }
7795 }
7796 xmlFree(name);
7797 ctxt->instate = XML_PARSER_CONTENT;
7798#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007799 xmlGenericError(xmlGenericErrorContext,
7800 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007801#endif
7802 break;
7803 }
Daniel Veillarde715dd22000-08-29 18:29:38 +00007804 case XML_PARSER_CONTENT: {
7805 const xmlChar *test;
7806 int cons;
7807 xmlChar tok;
7808
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007809 /*
7810 * Handle preparsed entities and charRef
7811 */
7812 if (ctxt->token != 0) {
7813 xmlChar cur[2] = { 0 , 0 } ;
7814
7815 cur[0] = (xmlChar) ctxt->token;
Daniel Veillardcf461992000-03-14 18:30:20 +00007816 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
7817 (ctxt->sax->characters != NULL))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007818 ctxt->sax->characters(ctxt->userData, cur, 1);
7819 ctxt->token = 0;
7820 }
Daniel Veillardcf461992000-03-14 18:30:20 +00007821 if ((avail < 2) && (ctxt->inputNr == 1))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007822 goto done;
Daniel Veillardcf461992000-03-14 18:30:20 +00007823 cur = ctxt->input->cur[0];
7824 next = ctxt->input->cur[1];
Daniel Veillarde715dd22000-08-29 18:29:38 +00007825
7826 test = CUR_PTR;
7827 cons = ctxt->input->consumed;
7828 tok = ctxt->token;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007829 if ((cur == '<') && (next == '?')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007830 if ((!terminate) &&
7831 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007832 goto done;
7833#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007834 xmlGenericError(xmlGenericErrorContext,
7835 "PP: Parsing PI\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007836#endif
7837 xmlParsePI(ctxt);
7838 } else if ((cur == '<') && (next == '!') &&
Daniel Veillardcf461992000-03-14 18:30:20 +00007839 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007840 if ((!terminate) &&
7841 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007842 goto done;
7843#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007844 xmlGenericError(xmlGenericErrorContext,
7845 "PP: Parsing Comment\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007846#endif
7847 xmlParseComment(ctxt);
7848 ctxt->instate = XML_PARSER_CONTENT;
Daniel Veillardcf461992000-03-14 18:30:20 +00007849 } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
7850 (ctxt->input->cur[2] == '[') && (NXT(3) == 'C') &&
7851 (ctxt->input->cur[4] == 'D') && (NXT(5) == 'A') &&
7852 (ctxt->input->cur[6] == 'T') && (NXT(7) == 'A') &&
7853 (ctxt->input->cur[8] == '[')) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007854 SKIP(9);
7855 ctxt->instate = XML_PARSER_CDATA_SECTION;
7856#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007857 xmlGenericError(xmlGenericErrorContext,
7858 "PP: entering CDATA_SECTION\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007859#endif
7860 break;
7861 } else if ((cur == '<') && (next == '!') &&
7862 (avail < 9)) {
7863 goto done;
7864 } else if ((cur == '<') && (next == '/')) {
7865 ctxt->instate = XML_PARSER_END_TAG;
7866#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007867 xmlGenericError(xmlGenericErrorContext,
7868 "PP: entering END_TAG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007869#endif
7870 break;
7871 } else if (cur == '<') {
7872 ctxt->instate = XML_PARSER_START_TAG;
7873#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007874 xmlGenericError(xmlGenericErrorContext,
7875 "PP: entering START_TAG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007876#endif
7877 break;
7878 } else if (cur == '&') {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007879 if ((!terminate) &&
7880 (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007881 goto done;
7882#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007883 xmlGenericError(xmlGenericErrorContext,
7884 "PP: Parsing Reference\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007885#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007886 xmlParseReference(ctxt);
7887 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00007888 /* TODO Avoid the extra copy, handle directly !!! */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007889 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00007890 * Goal of the following test is:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007891 * - minimize calls to the SAX 'character' callback
7892 * when they are mergeable
7893 * - handle an problem for isBlank when we only parse
7894 * a sequence of blank chars and the next one is
7895 * not available to check against '<' presence.
7896 * - tries to homogenize the differences in SAX
7897 * callbacks beween the push and pull versions
7898 * of the parser.
7899 */
7900 if ((ctxt->inputNr == 1) &&
7901 (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
Daniel Veillard71b656e2000-01-05 14:46:17 +00007902 if ((!terminate) &&
7903 (xmlParseLookupSequence(ctxt, '<', 0, 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007904 goto done;
7905 }
7906 ctxt->checkIndex = 0;
7907#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007908 xmlGenericError(xmlGenericErrorContext,
7909 "PP: Parsing char data\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007910#endif
7911 xmlParseCharData(ctxt, 0);
7912 }
7913 /*
7914 * Pop-up of finished entities.
7915 */
Daniel Veillardcf461992000-03-14 18:30:20 +00007916 while ((RAW == 0) && (ctxt->inputNr > 1))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007917 xmlPopInput(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +00007918 if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
7919 (tok == ctxt->token)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00007920 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
Daniel Veillarde715dd22000-08-29 18:29:38 +00007921 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
7922 ctxt->sax->error(ctxt->userData,
7923 "detected an error in element content\n");
Daniel Veillarde715dd22000-08-29 18:29:38 +00007924 ctxt->wellFormed = 0;
7925 ctxt->disableSAX = 1;
7926 ctxt->instate = XML_PARSER_EOF;
7927 break;
7928 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007929 break;
Daniel Veillarde715dd22000-08-29 18:29:38 +00007930 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007931 case XML_PARSER_CDATA_SECTION: {
7932 /*
7933 * The Push mode need to have the SAX callback for
7934 * cdataBlock merge back contiguous callbacks.
7935 */
7936 int base;
7937
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007938 base = xmlParseLookupSequence(ctxt, ']', ']', '>');
7939 if (base < 0) {
7940 if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
Daniel Veillardcf461992000-03-14 18:30:20 +00007941 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007942 if (ctxt->sax->cdataBlock != NULL)
Daniel Veillardcf461992000-03-14 18:30:20 +00007943 ctxt->sax->cdataBlock(ctxt->userData, ctxt->input->cur,
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007944 XML_PARSER_BIG_BUFFER_SIZE);
7945 }
7946 SKIP(XML_PARSER_BIG_BUFFER_SIZE);
7947 ctxt->checkIndex = 0;
7948 }
7949 goto done;
7950 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00007951 if ((ctxt->sax != NULL) && (base > 0) &&
7952 (!ctxt->disableSAX)) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007953 if (ctxt->sax->cdataBlock != NULL)
7954 ctxt->sax->cdataBlock(ctxt->userData,
Daniel Veillardcf461992000-03-14 18:30:20 +00007955 ctxt->input->cur, base);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007956 }
7957 SKIP(base + 3);
7958 ctxt->checkIndex = 0;
7959 ctxt->instate = XML_PARSER_CONTENT;
7960#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007961 xmlGenericError(xmlGenericErrorContext,
7962 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007963#endif
7964 }
7965 break;
7966 }
Daniel Veillard5e5c6231999-12-29 12:49:06 +00007967 case XML_PARSER_END_TAG:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007968 if (avail < 2)
7969 goto done;
Daniel Veillard71b656e2000-01-05 14:46:17 +00007970 if ((!terminate) &&
7971 (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007972 goto done;
7973 xmlParseEndTag(ctxt);
7974 if (ctxt->name == NULL) {
7975 ctxt->instate = XML_PARSER_EPILOG;
7976#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007977 xmlGenericError(xmlGenericErrorContext,
7978 "PP: entering EPILOG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007979#endif
7980 } else {
7981 ctxt->instate = XML_PARSER_CONTENT;
7982#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00007983 xmlGenericError(xmlGenericErrorContext,
7984 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007985#endif
7986 }
7987 break;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00007988 case XML_PARSER_DTD: {
7989 /*
7990 * Sorry but progressive parsing of the internal subset
7991 * is not expected to be supported. We first check that
7992 * the full content of the internal subset is available and
7993 * the parsing is launched only at that point.
7994 * Internal subset ends up with "']' S? '>'" in an unescaped
7995 * section and not in a ']]>' sequence which are conditional
7996 * sections (whoever argued to keep that crap in XML deserve
7997 * a place in hell !).
7998 */
7999 int base, i;
8000 xmlChar *buf;
8001 xmlChar quote = 0;
8002
Daniel Veillardcf461992000-03-14 18:30:20 +00008003 base = ctxt->input->cur - ctxt->input->base;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008004 if (base < 0) return(0);
8005 if (ctxt->checkIndex > base)
8006 base = ctxt->checkIndex;
Daniel Veillardcf461992000-03-14 18:30:20 +00008007 buf = ctxt->input->buf->buffer->content;
Daniel Veillard3f6f7f62000-06-30 17:58:25 +00008008 for (;(unsigned int) base < ctxt->input->buf->buffer->use;
8009 base++) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008010 if (quote != 0) {
8011 if (buf[base] == quote)
8012 quote = 0;
8013 continue;
8014 }
8015 if (buf[base] == '"') {
8016 quote = '"';
8017 continue;
8018 }
8019 if (buf[base] == '\'') {
8020 quote = '\'';
8021 continue;
8022 }
8023 if (buf[base] == ']') {
Daniel Veillard3f6f7f62000-06-30 17:58:25 +00008024 if ((unsigned int) base +1 >=
8025 ctxt->input->buf->buffer->use)
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008026 break;
8027 if (buf[base + 1] == ']') {
8028 /* conditional crap, skip both ']' ! */
8029 base++;
8030 continue;
8031 }
Daniel Veillard3f6f7f62000-06-30 17:58:25 +00008032 for (i = 0;
8033 (unsigned int) base + i < ctxt->input->buf->buffer->use;
8034 i++) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008035 if (buf[base + i] == '>')
8036 goto found_end_int_subset;
8037 }
8038 break;
8039 }
8040 }
8041 /*
8042 * We didn't found the end of the Internal subset
8043 */
8044 if (quote == 0)
8045 ctxt->checkIndex = base;
8046#ifdef DEBUG_PUSH
8047 if (next == 0)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008048 xmlGenericError(xmlGenericErrorContext,
8049 "PP: lookup of int subset end filed\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008050#endif
8051 goto done;
8052
8053found_end_int_subset:
8054 xmlParseInternalSubset(ctxt);
Daniel Veillardcf461992000-03-14 18:30:20 +00008055 ctxt->inSubset = 2;
8056 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
8057 (ctxt->sax->externalSubset != NULL))
8058 ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
8059 ctxt->extSubSystem, ctxt->extSubURI);
8060 ctxt->inSubset = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008061 ctxt->instate = XML_PARSER_PROLOG;
8062 ctxt->checkIndex = 0;
8063#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008064 xmlGenericError(xmlGenericErrorContext,
8065 "PP: entering PROLOG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008066#endif
8067 break;
8068 }
Daniel Veillard7f858501999-11-17 17:32:38 +00008069 case XML_PARSER_COMMENT:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008070 xmlGenericError(xmlGenericErrorContext,
8071 "PP: internal error, state == COMMENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008072 ctxt->instate = XML_PARSER_CONTENT;
8073#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008074 xmlGenericError(xmlGenericErrorContext,
8075 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008076#endif
8077 break;
8078 case XML_PARSER_PI:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008079 xmlGenericError(xmlGenericErrorContext,
8080 "PP: internal error, state == PI\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008081 ctxt->instate = XML_PARSER_CONTENT;
8082#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008083 xmlGenericError(xmlGenericErrorContext,
8084 "PP: entering CONTENT\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008085#endif
8086 break;
8087 case XML_PARSER_ENTITY_DECL:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008088 xmlGenericError(xmlGenericErrorContext,
8089 "PP: internal error, state == ENTITY_DECL\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008090 ctxt->instate = XML_PARSER_DTD;
8091#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008092 xmlGenericError(xmlGenericErrorContext,
8093 "PP: entering DTD\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008094#endif
8095 break;
8096 case XML_PARSER_ENTITY_VALUE:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008097 xmlGenericError(xmlGenericErrorContext,
8098 "PP: internal error, state == ENTITY_VALUE\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008099 ctxt->instate = XML_PARSER_CONTENT;
8100#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008101 xmlGenericError(xmlGenericErrorContext,
8102 "PP: entering DTD\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008103#endif
8104 break;
8105 case XML_PARSER_ATTRIBUTE_VALUE:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008106 xmlGenericError(xmlGenericErrorContext,
8107 "PP: internal error, state == ATTRIBUTE_VALUE\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008108 ctxt->instate = XML_PARSER_START_TAG;
8109#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008110 xmlGenericError(xmlGenericErrorContext,
8111 "PP: entering START_TAG\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008112#endif
8113 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00008114 case XML_PARSER_SYSTEM_LITERAL:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008115 xmlGenericError(xmlGenericErrorContext,
8116 "PP: internal error, state == SYSTEM_LITERAL\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00008117 ctxt->instate = XML_PARSER_START_TAG;
8118#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008119 xmlGenericError(xmlGenericErrorContext,
8120 "PP: entering START_TAG\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00008121#endif
8122 break;
Daniel Veillard7f858501999-11-17 17:32:38 +00008123 }
8124 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008125done:
8126#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008127 xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008128#endif
Daniel Veillard7f858501999-11-17 17:32:38 +00008129 return(ret);
8130}
8131
8132/**
Daniel Veillard71b656e2000-01-05 14:46:17 +00008133 * xmlParseTry:
8134 * @ctxt: an XML parser context
8135 *
8136 * Try to progress on parsing
8137 *
8138 * Returns zero if no parsing was possible
8139 */
8140int
8141xmlParseTry(xmlParserCtxtPtr ctxt) {
8142 return(xmlParseTryOrFinish(ctxt, 0));
8143}
8144
8145/**
Daniel Veillard7f858501999-11-17 17:32:38 +00008146 * xmlParseChunk:
8147 * @ctxt: an XML parser context
8148 * @chunk: an char array
8149 * @size: the size in byte of the chunk
8150 * @terminate: last chunk indicator
8151 *
8152 * Parse a Chunk of memory
8153 *
8154 * Returns zero if no error, the xmlParserErrors otherwise.
8155 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008156int
Daniel Veillard7f858501999-11-17 17:32:38 +00008157xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
8158 int terminate) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00008159 if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008160 (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) {
8161 int base = ctxt->input->base - ctxt->input->buf->buffer->content;
8162 int cur = ctxt->input->cur - ctxt->input->base;
8163
Daniel Veillarda819dac1999-11-24 18:04:22 +00008164 xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008165 ctxt->input->base = ctxt->input->buf->buffer->content + base;
8166 ctxt->input->cur = ctxt->input->base + cur;
8167#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008168 xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008169#endif
8170
Daniel Veillardd0f7f742000-02-02 17:42:48 +00008171 if ((terminate) || (ctxt->input->buf->buffer->use > 80))
8172 xmlParseTryOrFinish(ctxt, terminate);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008173 } else if (ctxt->instate != XML_PARSER_EOF)
Daniel Veillardc2def842000-11-07 14:21:01 +00008174 if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
8175 xmlParserInputBufferPtr in = ctxt->input->buf;
8176 int nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
8177 if (nbchars < 0) {
8178 xmlGenericError(xmlGenericErrorContext,
8179 "xmlParseChunk: encoder error\n");
8180 return(XML_ERR_INVALID_ENCODING);
8181 }
8182 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00008183 xmlParseTryOrFinish(ctxt, terminate);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008184 if (terminate) {
Daniel Veillardcf461992000-03-14 18:30:20 +00008185 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00008186 * Check for termination
8187 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008188 if ((ctxt->instate != XML_PARSER_EOF) &&
8189 (ctxt->instate != XML_PARSER_EPILOG)) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008190 ctxt->errNo = XML_ERR_DOCUMENT_END;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008191 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8192 ctxt->sax->error(ctxt->userData,
8193 "Extra content at the end of the document\n");
8194 ctxt->wellFormed = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00008195 ctxt->disableSAX = 1;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008196 }
8197 if (ctxt->instate != XML_PARSER_EOF) {
Daniel Veillardcf461992000-03-14 18:30:20 +00008198 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL) &&
8199 (!ctxt->disableSAX))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008200 ctxt->sax->endDocument(ctxt->userData);
8201 }
8202 ctxt->instate = XML_PARSER_EOF;
Daniel Veillard7f858501999-11-17 17:32:38 +00008203 }
8204 return((xmlParserErrors) ctxt->errNo);
8205}
8206
8207/************************************************************************
8208 * *
Daniel Veillardb05deb71999-08-10 19:04:08 +00008209 * I/O front end functions to the parser *
8210 * *
8211 ************************************************************************/
8212
Daniel Veillard11e00581998-10-24 18:27:49 +00008213/**
Daniel Veillardb1059e22000-09-16 14:02:43 +00008214 * xmlStopParser:
Daniel Veillard3f6f7f62000-06-30 17:58:25 +00008215 * @ctxt: an XML parser context
8216 *
8217 * Blocks further parser processing
8218 */
8219void
8220xmlStopParser(xmlParserCtxtPtr ctxt) {
8221 ctxt->instate = XML_PARSER_EOF;
8222 if (ctxt->input != NULL)
8223 ctxt->input->cur = BAD_CAST"";
8224}
8225
8226/**
8227 * xmlCreatePushParserCtxt:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008228 * @sax: a SAX handler
8229 * @user_data: The user data returned on SAX callbacks
8230 * @chunk: a pointer to an array of chars
8231 * @size: number of chars in the array
8232 * @filename: an optional file name or URI
8233 *
8234 * Create a parser context for using the XML parser in push mode
8235 * To allow content encoding detection, @size should be >= 4
8236 * The value of @filename is used for fetching external entities
8237 * and error/warning reports.
8238 *
8239 * Returns the new parser context or NULL
8240 */
8241xmlParserCtxtPtr
8242xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
8243 const char *chunk, int size, const char *filename) {
8244 xmlParserCtxtPtr ctxt;
8245 xmlParserInputPtr inputStream;
8246 xmlParserInputBufferPtr buf;
8247 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
8248
8249 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00008250 * plug some encoding conversion routines
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008251 */
8252 if ((chunk != NULL) && (size >= 4))
Daniel Veillardcf461992000-03-14 18:30:20 +00008253 enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008254
8255 buf = xmlAllocParserInputBuffer(enc);
8256 if (buf == NULL) return(NULL);
8257
8258 ctxt = xmlNewParserCtxt();
8259 if (ctxt == NULL) {
8260 xmlFree(buf);
8261 return(NULL);
8262 }
8263 if (sax != NULL) {
8264 if (ctxt->sax != &xmlDefaultSAXHandler)
8265 xmlFree(ctxt->sax);
8266 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
8267 if (ctxt->sax == NULL) {
8268 xmlFree(buf);
8269 xmlFree(ctxt);
8270 return(NULL);
8271 }
8272 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
8273 if (user_data != NULL)
8274 ctxt->userData = user_data;
8275 }
8276 if (filename == NULL) {
8277 ctxt->directory = NULL;
8278 } else {
8279 ctxt->directory = xmlParserGetDirectory(filename);
8280 }
8281
8282 inputStream = xmlNewInputStream(ctxt);
8283 if (inputStream == NULL) {
8284 xmlFreeParserCtxt(ctxt);
8285 return(NULL);
8286 }
8287
8288 if (filename == NULL)
8289 inputStream->filename = NULL;
8290 else
8291 inputStream->filename = xmlMemStrdup(filename);
8292 inputStream->buf = buf;
8293 inputStream->base = inputStream->buf->buffer->content;
8294 inputStream->cur = inputStream->buf->buffer->content;
Daniel Veillardcf461992000-03-14 18:30:20 +00008295 if (enc != XML_CHAR_ENCODING_NONE) {
8296 xmlSwitchEncoding(ctxt, enc);
8297 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008298
8299 inputPush(ctxt, inputStream);
8300
8301 if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
8302 (ctxt->input->buf != NULL)) {
8303 xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
8304#ifdef DEBUG_PUSH
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008305 xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00008306#endif
8307 }
8308
8309 return(ctxt);
8310}
8311
8312/**
Daniel Veillard5e873c42000-04-12 13:27:38 +00008313 * xmlCreateIOParserCtxt:
8314 * @sax: a SAX handler
8315 * @user_data: The user data returned on SAX callbacks
8316 * @ioread: an I/O read function
8317 * @ioclose: an I/O close function
8318 * @ioctx: an I/O handler
8319 * @enc: the charset encoding if known
8320 *
8321 * Create a parser context for using the XML parser with an existing
8322 * I/O stream
8323 *
8324 * Returns the new parser context or NULL
8325 */
8326xmlParserCtxtPtr
8327xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
8328 xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
8329 void *ioctx, xmlCharEncoding enc) {
8330 xmlParserCtxtPtr ctxt;
8331 xmlParserInputPtr inputStream;
8332 xmlParserInputBufferPtr buf;
8333
8334 buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
8335 if (buf == NULL) return(NULL);
8336
8337 ctxt = xmlNewParserCtxt();
8338 if (ctxt == NULL) {
8339 xmlFree(buf);
8340 return(NULL);
8341 }
8342 if (sax != NULL) {
8343 if (ctxt->sax != &xmlDefaultSAXHandler)
8344 xmlFree(ctxt->sax);
8345 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
8346 if (ctxt->sax == NULL) {
8347 xmlFree(buf);
8348 xmlFree(ctxt);
8349 return(NULL);
8350 }
8351 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
8352 if (user_data != NULL)
8353 ctxt->userData = user_data;
8354 }
8355
8356 inputStream = xmlNewIOInputStream(ctxt, buf, enc);
8357 if (inputStream == NULL) {
8358 xmlFreeParserCtxt(ctxt);
8359 return(NULL);
8360 }
8361 inputPush(ctxt, inputStream);
8362
8363 return(ctxt);
8364}
8365
Daniel Veillardb1059e22000-09-16 14:02:43 +00008366/************************************************************************
8367 * *
8368 * Front ends when parsing a Dtd *
8369 * *
8370 ************************************************************************/
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00008371
8372/**
Daniel Veillard2ffc3592000-10-30 15:36:47 +00008373 * xmlIOParseDTD:
8374 * @sax: the SAX handler block or NULL
8375 * @input: an Input Buffer
8376 * @enc: the charset encoding if known
8377 *
8378 * Load and parse a DTD
8379 *
8380 * Returns the resulting xmlDtdPtr or NULL in case of error.
Daniel Veillarda4964b72000-10-31 18:23:44 +00008381 * @input will be freed at parsing end.
Daniel Veillard2ffc3592000-10-30 15:36:47 +00008382 */
8383
8384xmlDtdPtr
8385xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
8386 xmlCharEncoding enc) {
8387 xmlDtdPtr ret = NULL;
8388 xmlParserCtxtPtr ctxt;
8389 xmlParserInputPtr pinput = NULL;
8390
8391 if (input == NULL)
8392 return(NULL);
8393
8394 ctxt = xmlNewParserCtxt();
8395 if (ctxt == NULL) {
8396 return(NULL);
8397 }
8398
8399 /*
8400 * Set-up the SAX context
8401 */
8402 if (sax != NULL) {
8403 if (ctxt->sax != NULL)
8404 xmlFree(ctxt->sax);
8405 ctxt->sax = sax;
8406 ctxt->userData = NULL;
8407 }
8408
8409 /*
8410 * generate a parser input from the I/O handler
8411 */
8412
8413 pinput = xmlNewIOInputStream(ctxt, input, enc);
8414 if (pinput == NULL) {
8415 if (sax != NULL) ctxt->sax = NULL;
8416 xmlFreeParserCtxt(ctxt);
8417 return(NULL);
8418 }
8419
8420 /*
8421 * plug some encoding conversion routines here.
8422 */
8423 xmlPushInput(ctxt, pinput);
8424
8425 pinput->filename = NULL;
8426 pinput->line = 1;
8427 pinput->col = 1;
8428 pinput->base = ctxt->input->cur;
8429 pinput->cur = ctxt->input->cur;
8430 pinput->free = NULL;
8431
8432 /*
8433 * let's parse that entity knowing it's an external subset.
8434 */
8435 ctxt->inSubset = 2;
8436 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
8437 ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
8438 BAD_CAST "none", BAD_CAST "none");
8439 xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
8440
8441 if (ctxt->myDoc != NULL) {
8442 if (ctxt->wellFormed) {
8443 ret = ctxt->myDoc->extSubset;
8444 ctxt->myDoc->extSubset = NULL;
8445 } else {
8446 ret = NULL;
8447 }
8448 xmlFreeDoc(ctxt->myDoc);
8449 ctxt->myDoc = NULL;
8450 }
8451 if (sax != NULL) ctxt->sax = NULL;
8452 xmlFreeParserCtxt(ctxt);
8453
8454 return(ret);
8455}
8456
8457/**
Daniel Veillardcf461992000-03-14 18:30:20 +00008458 * xmlSAXParseDTD:
Daniel Veillard011b63c1999-06-02 17:44:04 +00008459 * @sax: the SAX handler block
8460 * @ExternalID: a NAME* containing the External ID of the DTD
8461 * @SystemID: a NAME* containing the URL to the DTD
8462 *
8463 * Load and parse an external subset.
8464 *
8465 * Returns the resulting xmlDtdPtr or NULL in case of error.
8466 */
8467
8468xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00008469xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
8470 const xmlChar *SystemID) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00008471 xmlDtdPtr ret = NULL;
8472 xmlParserCtxtPtr ctxt;
Daniel Veillard14fff061999-06-22 21:49:07 +00008473 xmlParserInputPtr input = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00008474 xmlCharEncoding enc;
8475
8476 if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
8477
Daniel Veillardb05deb71999-08-10 19:04:08 +00008478 ctxt = xmlNewParserCtxt();
Daniel Veillard011b63c1999-06-02 17:44:04 +00008479 if (ctxt == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00008480 return(NULL);
8481 }
Daniel Veillard011b63c1999-06-02 17:44:04 +00008482
8483 /*
8484 * Set-up the SAX context
8485 */
Daniel Veillard011b63c1999-06-02 17:44:04 +00008486 if (sax != NULL) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00008487 if (ctxt->sax != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00008488 xmlFree(ctxt->sax);
Daniel Veillard011b63c1999-06-02 17:44:04 +00008489 ctxt->sax = sax;
8490 ctxt->userData = NULL;
8491 }
8492
8493 /*
8494 * Ask the Entity resolver to load the damn thing
8495 */
8496
8497 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
8498 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
8499 if (input == NULL) {
Daniel Veillard97fea181999-06-26 23:07:37 +00008500 if (sax != NULL) ctxt->sax = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00008501 xmlFreeParserCtxt(ctxt);
8502 return(NULL);
8503 }
8504
8505 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00008506 * plug some encoding conversion routines here.
Daniel Veillard011b63c1999-06-02 17:44:04 +00008507 */
8508 xmlPushInput(ctxt, input);
Daniel Veillardcf461992000-03-14 18:30:20 +00008509 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
Daniel Veillard011b63c1999-06-02 17:44:04 +00008510 xmlSwitchEncoding(ctxt, enc);
8511
Daniel Veillardb05deb71999-08-10 19:04:08 +00008512 if (input->filename == NULL)
Daniel Veillardcf461992000-03-14 18:30:20 +00008513 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillard011b63c1999-06-02 17:44:04 +00008514 input->line = 1;
8515 input->col = 1;
8516 input->base = ctxt->input->cur;
8517 input->cur = ctxt->input->cur;
8518 input->free = NULL;
8519
8520 /*
8521 * let's parse that entity knowing it's an external subset.
8522 */
Daniel Veillard06047432000-04-24 11:33:38 +00008523 ctxt->inSubset = 2;
8524 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
8525 ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
8526 ExternalID, SystemID);
Daniel Veillard011b63c1999-06-02 17:44:04 +00008527 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
8528
8529 if (ctxt->myDoc != NULL) {
8530 if (ctxt->wellFormed) {
Daniel Veillard06047432000-04-24 11:33:38 +00008531 ret = ctxt->myDoc->extSubset;
8532 ctxt->myDoc->extSubset = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00008533 } else {
8534 ret = NULL;
8535 }
8536 xmlFreeDoc(ctxt->myDoc);
8537 ctxt->myDoc = NULL;
8538 }
Daniel Veillard97fea181999-06-26 23:07:37 +00008539 if (sax != NULL) ctxt->sax = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +00008540 xmlFreeParserCtxt(ctxt);
8541
8542 return(ret);
8543}
8544
8545/**
Daniel Veillardcf461992000-03-14 18:30:20 +00008546 * xmlParseDTD:
Daniel Veillard011b63c1999-06-02 17:44:04 +00008547 * @ExternalID: a NAME* containing the External ID of the DTD
8548 * @SystemID: a NAME* containing the URL to the DTD
8549 *
8550 * Load and parse an external subset.
8551 *
8552 * Returns the resulting xmlDtdPtr or NULL in case of error.
8553 */
8554
8555xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00008556xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00008557 return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
8558}
8559
Daniel Veillardb1059e22000-09-16 14:02:43 +00008560/************************************************************************
8561 * *
8562 * Front ends when parsing an Entity *
8563 * *
8564 ************************************************************************/
8565
Daniel Veillard011b63c1999-06-02 17:44:04 +00008566/**
Daniel Veillardcf461992000-03-14 18:30:20 +00008567 * xmlSAXParseBalancedChunk:
Daniel Veillard0142b842000-01-14 14:45:24 +00008568 * @ctx: an XML parser context (possibly NULL)
8569 * @sax: the SAX handler bloc (possibly NULL)
8570 * @user_data: The user data returned on SAX callbacks (possibly NULL)
8571 * @input: a parser input stream
8572 * @enc: the encoding
8573 *
8574 * Parse a well-balanced chunk of an XML document
8575 * The user has to provide SAX callback block whose routines will be
8576 * called by the parser
8577 * The allowed sequence for the Well Balanced Chunk is the one defined by
8578 * the content production in the XML grammar:
8579 *
8580 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
8581 *
Daniel Veillardcf461992000-03-14 18:30:20 +00008582 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
Daniel Veillard0142b842000-01-14 14:45:24 +00008583 * the error code otherwise
8584 */
8585
8586int
8587xmlSAXParseBalancedChunk(xmlParserCtxtPtr ctx, xmlSAXHandlerPtr sax,
8588 void *user_data, xmlParserInputPtr input,
8589 xmlCharEncoding enc) {
8590 xmlParserCtxtPtr ctxt;
8591 int ret;
8592
8593 if (input == NULL) return(-1);
8594
8595 if (ctx != NULL)
8596 ctxt = ctx;
8597 else {
8598 ctxt = xmlNewParserCtxt();
8599 if (ctxt == NULL)
8600 return(-1);
8601 if (sax == NULL)
8602 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
8603 }
8604
8605 /*
8606 * Set-up the SAX context
8607 */
8608 if (sax != NULL) {
8609 if (ctxt->sax != NULL)
8610 xmlFree(ctxt->sax);
8611 ctxt->sax = sax;
8612 ctxt->userData = user_data;
8613 }
8614
8615 /*
8616 * plug some encoding conversion routines here.
8617 */
8618 xmlPushInput(ctxt, input);
8619 if (enc != XML_CHAR_ENCODING_NONE)
8620 xmlSwitchEncoding(ctxt, enc);
8621
8622 /*
8623 * let's parse that entity knowing it's an external subset.
8624 */
8625 xmlParseContent(ctxt);
8626 ret = ctxt->errNo;
8627
8628 if (ctx == NULL) {
8629 if (sax != NULL)
8630 ctxt->sax = NULL;
8631 else
8632 xmlFreeDoc(ctxt->myDoc);
8633 xmlFreeParserCtxt(ctxt);
8634 }
8635 return(ret);
8636}
8637
8638/**
Daniel Veillard87b95392000-08-12 21:12:04 +00008639 * xmlParseCtxtExternalEntity:
8640 * @ctx: the existing parsing context
8641 * @URL: the URL for the entity to load
8642 * @ID: the System ID for the entity to load
8643 * @list: the return value for the set of parsed nodes
8644 *
8645 * Parse an external general entity within an existing parsing context
8646 * An external general parsed entity is well-formed if it matches the
8647 * production labeled extParsedEnt.
8648 *
8649 * [78] extParsedEnt ::= TextDecl? content
8650 *
8651 * Returns 0 if the entity is well formed, -1 in case of args problem and
8652 * the parser error code otherwise
8653 */
8654
8655int
8656xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
8657 const xmlChar *ID, xmlNodePtr *list) {
8658 xmlParserCtxtPtr ctxt;
8659 xmlDocPtr newDoc;
8660 xmlSAXHandlerPtr oldsax = NULL;
8661 int ret = 0;
8662
8663 if (ctx->depth > 40) {
8664 return(XML_ERR_ENTITY_LOOP);
8665 }
8666
8667 if (list != NULL)
8668 *list = NULL;
8669 if ((URL == NULL) && (ID == NULL))
8670 return(-1);
8671 if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
8672 return(-1);
8673
8674
Daniel Veillard39c7d712000-09-10 16:14:55 +00008675 ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
Daniel Veillard87b95392000-08-12 21:12:04 +00008676 if (ctxt == NULL) return(-1);
8677 ctxt->userData = ctxt;
8678 oldsax = ctxt->sax;
8679 ctxt->sax = ctx->sax;
8680 newDoc = xmlNewDoc(BAD_CAST "1.0");
8681 if (newDoc == NULL) {
8682 xmlFreeParserCtxt(ctxt);
8683 return(-1);
8684 }
8685 if (ctx->myDoc != NULL) {
8686 newDoc->intSubset = ctx->myDoc->intSubset;
8687 newDoc->extSubset = ctx->myDoc->extSubset;
8688 }
8689 if (ctx->myDoc->URL != NULL) {
8690 newDoc->URL = xmlStrdup(ctx->myDoc->URL);
8691 }
8692 newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
8693 if (newDoc->children == NULL) {
8694 ctxt->sax = oldsax;
8695 xmlFreeParserCtxt(ctxt);
8696 newDoc->intSubset = NULL;
8697 newDoc->extSubset = NULL;
8698 xmlFreeDoc(newDoc);
8699 return(-1);
8700 }
8701 nodePush(ctxt, newDoc->children);
8702 if (ctx->myDoc == NULL) {
8703 ctxt->myDoc = newDoc;
8704 } else {
8705 ctxt->myDoc = ctx->myDoc;
8706 newDoc->children->doc = ctx->myDoc;
8707 }
8708
8709 /*
8710 * Parse a possible text declaration first
8711 */
8712 GROW;
8713 if ((RAW == '<') && (NXT(1) == '?') &&
8714 (NXT(2) == 'x') && (NXT(3) == 'm') &&
8715 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
8716 xmlParseTextDecl(ctxt);
8717 }
8718
8719 /*
8720 * Doing validity checking on chunk doesn't make sense
8721 */
8722 ctxt->instate = XML_PARSER_CONTENT;
8723 ctxt->validate = ctx->validate;
8724 ctxt->depth = ctx->depth + 1;
8725 ctxt->replaceEntities = ctx->replaceEntities;
8726 if (ctxt->validate) {
8727 ctxt->vctxt.error = ctx->vctxt.error;
8728 ctxt->vctxt.warning = ctx->vctxt.warning;
8729 /* Allocate the Node stack */
8730 ctxt->vctxt.nodeTab = (xmlNodePtr *) xmlMalloc(4 * sizeof(xmlNodePtr));
Daniel Veillard39c7d712000-09-10 16:14:55 +00008731 if (ctxt->vctxt.nodeTab == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00008732 xmlGenericError(xmlGenericErrorContext,
8733 "xmlParseCtxtExternalEntity: out of memory\n");
Daniel Veillard39c7d712000-09-10 16:14:55 +00008734 ctxt->validate = 0;
8735 ctxt->vctxt.error = NULL;
8736 ctxt->vctxt.warning = NULL;
8737 } else {
8738 ctxt->vctxt.nodeNr = 0;
8739 ctxt->vctxt.nodeMax = 4;
8740 ctxt->vctxt.node = NULL;
8741 }
Daniel Veillard87b95392000-08-12 21:12:04 +00008742 } else {
8743 ctxt->vctxt.error = NULL;
8744 ctxt->vctxt.warning = NULL;
8745 }
8746
8747 xmlParseContent(ctxt);
8748
8749 if ((RAW == '<') && (NXT(1) == '/')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008750 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillard87b95392000-08-12 21:12:04 +00008751 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8752 ctxt->sax->error(ctxt->userData,
8753 "chunk is not well balanced\n");
8754 ctxt->wellFormed = 0;
8755 ctxt->disableSAX = 1;
Daniel Veillard87b95392000-08-12 21:12:04 +00008756 } else if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008757 ctxt->errNo = XML_ERR_EXTRA_CONTENT;
Daniel Veillard87b95392000-08-12 21:12:04 +00008758 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8759 ctxt->sax->error(ctxt->userData,
8760 "extra content at the end of well balanced chunk\n");
8761 ctxt->wellFormed = 0;
8762 ctxt->disableSAX = 1;
Daniel Veillard87b95392000-08-12 21:12:04 +00008763 }
8764 if (ctxt->node != newDoc->children) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008765 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillard87b95392000-08-12 21:12:04 +00008766 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8767 ctxt->sax->error(ctxt->userData,
8768 "chunk is not well balanced\n");
8769 ctxt->wellFormed = 0;
8770 ctxt->disableSAX = 1;
Daniel Veillard87b95392000-08-12 21:12:04 +00008771 }
8772
8773 if (!ctxt->wellFormed) {
8774 if (ctxt->errNo == 0)
8775 ret = 1;
8776 else
8777 ret = ctxt->errNo;
8778 } else {
8779 if (list != NULL) {
8780 xmlNodePtr cur;
8781
8782 /*
8783 * Return the newly created nodeset after unlinking it from
8784 * they pseudo parent.
8785 */
8786 cur = newDoc->children->children;
8787 *list = cur;
8788 while (cur != NULL) {
8789 cur->parent = NULL;
8790 cur = cur->next;
8791 }
8792 newDoc->children->children = NULL;
8793 }
8794 ret = 0;
8795 }
8796 ctxt->sax = oldsax;
8797 xmlFreeParserCtxt(ctxt);
8798 newDoc->intSubset = NULL;
8799 newDoc->extSubset = NULL;
8800 xmlFreeDoc(newDoc);
8801
8802 return(ret);
8803}
8804
8805/**
Daniel Veillardcf461992000-03-14 18:30:20 +00008806 * xmlParseExternalEntity:
Daniel Veillard0142b842000-01-14 14:45:24 +00008807 * @doc: the document the chunk pertains to
Daniel Veillardcf461992000-03-14 18:30:20 +00008808 * @sax: the SAX handler bloc (possibly NULL)
8809 * @user_data: The user data returned on SAX callbacks (possibly NULL)
8810 * @depth: Used for loop detection, use 0
8811 * @URL: the URL for the entity to load
8812 * @ID: the System ID for the entity to load
8813 * @list: the return value for the set of parsed nodes
Daniel Veillard0142b842000-01-14 14:45:24 +00008814 *
Daniel Veillardcf461992000-03-14 18:30:20 +00008815 * Parse an external general entity
8816 * An external general parsed entity is well-formed if it matches the
8817 * production labeled extParsedEnt.
8818 *
8819 * [78] extParsedEnt ::= TextDecl? content
8820 *
8821 * Returns 0 if the entity is well formed, -1 in case of args problem and
8822 * the parser error code otherwise
Daniel Veillard0142b842000-01-14 14:45:24 +00008823 */
8824
Daniel Veillardcf461992000-03-14 18:30:20 +00008825int
8826xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
8827 int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) {
8828 xmlParserCtxtPtr ctxt;
8829 xmlDocPtr newDoc;
8830 xmlSAXHandlerPtr oldsax = NULL;
8831 int ret = 0;
8832
8833 if (depth > 40) {
8834 return(XML_ERR_ENTITY_LOOP);
8835 }
8836
8837
8838
8839 if (list != NULL)
8840 *list = NULL;
8841 if ((URL == NULL) && (ID == NULL))
8842 return(-1);
Daniel Veillard87b95392000-08-12 21:12:04 +00008843 if (doc == NULL) /* @@ relax but check for dereferences */
8844 return(-1);
Daniel Veillardcf461992000-03-14 18:30:20 +00008845
8846
Daniel Veillard39c7d712000-09-10 16:14:55 +00008847 ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00008848 if (ctxt == NULL) return(-1);
8849 ctxt->userData = ctxt;
8850 if (sax != NULL) {
8851 oldsax = ctxt->sax;
8852 ctxt->sax = sax;
8853 if (user_data != NULL)
8854 ctxt->userData = user_data;
8855 }
8856 newDoc = xmlNewDoc(BAD_CAST "1.0");
8857 if (newDoc == NULL) {
8858 xmlFreeParserCtxt(ctxt);
8859 return(-1);
8860 }
8861 if (doc != NULL) {
8862 newDoc->intSubset = doc->intSubset;
8863 newDoc->extSubset = doc->extSubset;
8864 }
8865 if (doc->URL != NULL) {
8866 newDoc->URL = xmlStrdup(doc->URL);
8867 }
8868 newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
8869 if (newDoc->children == NULL) {
8870 if (sax != NULL)
8871 ctxt->sax = oldsax;
8872 xmlFreeParserCtxt(ctxt);
8873 newDoc->intSubset = NULL;
8874 newDoc->extSubset = NULL;
8875 xmlFreeDoc(newDoc);
8876 return(-1);
8877 }
8878 nodePush(ctxt, newDoc->children);
8879 if (doc == NULL) {
8880 ctxt->myDoc = newDoc;
8881 } else {
8882 ctxt->myDoc = doc;
8883 newDoc->children->doc = doc;
8884 }
8885
8886 /*
8887 * Parse a possible text declaration first
8888 */
8889 GROW;
8890 if ((RAW == '<') && (NXT(1) == '?') &&
8891 (NXT(2) == 'x') && (NXT(3) == 'm') &&
8892 (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) {
8893 xmlParseTextDecl(ctxt);
8894 }
8895
8896 /*
8897 * Doing validity checking on chunk doesn't make sense
8898 */
8899 ctxt->instate = XML_PARSER_CONTENT;
8900 ctxt->validate = 0;
8901 ctxt->depth = depth;
8902
8903 xmlParseContent(ctxt);
8904
8905 if ((RAW == '<') && (NXT(1) == '/')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008906 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillardcf461992000-03-14 18:30:20 +00008907 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8908 ctxt->sax->error(ctxt->userData,
8909 "chunk is not well balanced\n");
8910 ctxt->wellFormed = 0;
8911 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00008912 } else if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008913 ctxt->errNo = XML_ERR_EXTRA_CONTENT;
Daniel Veillardcf461992000-03-14 18:30:20 +00008914 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8915 ctxt->sax->error(ctxt->userData,
8916 "extra content at the end of well balanced chunk\n");
8917 ctxt->wellFormed = 0;
8918 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00008919 }
8920 if (ctxt->node != newDoc->children) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00008921 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillardcf461992000-03-14 18:30:20 +00008922 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
8923 ctxt->sax->error(ctxt->userData,
8924 "chunk is not well balanced\n");
8925 ctxt->wellFormed = 0;
8926 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00008927 }
8928
8929 if (!ctxt->wellFormed) {
8930 if (ctxt->errNo == 0)
8931 ret = 1;
8932 else
8933 ret = ctxt->errNo;
8934 } else {
8935 if (list != NULL) {
8936 xmlNodePtr cur;
8937
8938 /*
8939 * Return the newly created nodeset after unlinking it from
8940 * they pseudo parent.
8941 */
8942 cur = newDoc->children->children;
8943 *list = cur;
8944 while (cur != NULL) {
8945 cur->parent = NULL;
8946 cur = cur->next;
8947 }
8948 newDoc->children->children = NULL;
8949 }
8950 ret = 0;
8951 }
8952 if (sax != NULL)
8953 ctxt->sax = oldsax;
8954 xmlFreeParserCtxt(ctxt);
8955 newDoc->intSubset = NULL;
8956 newDoc->extSubset = NULL;
8957 xmlFreeDoc(newDoc);
8958
8959 return(ret);
Daniel Veillard0142b842000-01-14 14:45:24 +00008960}
8961
8962/**
Daniel Veillardcf461992000-03-14 18:30:20 +00008963 * xmlParseBalancedChunk:
8964 * @doc: the document the chunk pertains to
8965 * @sax: the SAX handler bloc (possibly NULL)
8966 * @user_data: The user data returned on SAX callbacks (possibly NULL)
8967 * @depth: Used for loop detection, use 0
8968 * @string: the input string in UTF8 or ISO-Latin (zero terminated)
8969 * @list: the return value for the set of parsed nodes
8970 *
8971 * Parse a well-balanced chunk of an XML document
8972 * called by the parser
8973 * The allowed sequence for the Well Balanced Chunk is the one defined by
8974 * the content production in the XML grammar:
8975 *
8976 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
8977 *
8978 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
8979 * the parser error code otherwise
8980 */
8981
8982int
8983xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
8984 void *user_data, int depth, const xmlChar *string, xmlNodePtr *list) {
8985 xmlParserCtxtPtr ctxt;
8986 xmlDocPtr newDoc;
8987 xmlSAXHandlerPtr oldsax = NULL;
8988 int size;
8989 int ret = 0;
8990
8991 if (depth > 40) {
8992 return(XML_ERR_ENTITY_LOOP);
8993 }
8994
8995
8996 if (list != NULL)
8997 *list = NULL;
8998 if (string == NULL)
8999 return(-1);
9000
9001 size = xmlStrlen(string);
9002
9003 ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
9004 if (ctxt == NULL) return(-1);
9005 ctxt->userData = ctxt;
9006 if (sax != NULL) {
9007 oldsax = ctxt->sax;
9008 ctxt->sax = sax;
9009 if (user_data != NULL)
9010 ctxt->userData = user_data;
9011 }
9012 newDoc = xmlNewDoc(BAD_CAST "1.0");
9013 if (newDoc == NULL) {
9014 xmlFreeParserCtxt(ctxt);
9015 return(-1);
9016 }
9017 if (doc != NULL) {
9018 newDoc->intSubset = doc->intSubset;
9019 newDoc->extSubset = doc->extSubset;
9020 }
9021 newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
9022 if (newDoc->children == NULL) {
9023 if (sax != NULL)
9024 ctxt->sax = oldsax;
9025 xmlFreeParserCtxt(ctxt);
9026 newDoc->intSubset = NULL;
9027 newDoc->extSubset = NULL;
9028 xmlFreeDoc(newDoc);
9029 return(-1);
9030 }
9031 nodePush(ctxt, newDoc->children);
9032 if (doc == NULL) {
9033 ctxt->myDoc = newDoc;
9034 } else {
9035 ctxt->myDoc = doc;
9036 newDoc->children->doc = doc;
9037 }
9038 ctxt->instate = XML_PARSER_CONTENT;
9039 ctxt->depth = depth;
9040
9041 /*
9042 * Doing validity checking on chunk doesn't make sense
9043 */
9044 ctxt->validate = 0;
9045
9046 xmlParseContent(ctxt);
9047
9048 if ((RAW == '<') && (NXT(1) == '/')) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00009049 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillardcf461992000-03-14 18:30:20 +00009050 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
9051 ctxt->sax->error(ctxt->userData,
9052 "chunk is not well balanced\n");
9053 ctxt->wellFormed = 0;
9054 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00009055 } else if (RAW != 0) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00009056 ctxt->errNo = XML_ERR_EXTRA_CONTENT;
Daniel Veillardcf461992000-03-14 18:30:20 +00009057 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
9058 ctxt->sax->error(ctxt->userData,
9059 "extra content at the end of well balanced chunk\n");
9060 ctxt->wellFormed = 0;
9061 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00009062 }
9063 if (ctxt->node != newDoc->children) {
Daniel Veillarda2c6da92000-09-16 18:15:00 +00009064 ctxt->errNo = XML_ERR_NOT_WELL_BALANCED;
Daniel Veillardcf461992000-03-14 18:30:20 +00009065 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
9066 ctxt->sax->error(ctxt->userData,
9067 "chunk is not well balanced\n");
9068 ctxt->wellFormed = 0;
9069 ctxt->disableSAX = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +00009070 }
9071
9072 if (!ctxt->wellFormed) {
9073 if (ctxt->errNo == 0)
9074 ret = 1;
9075 else
9076 ret = ctxt->errNo;
9077 } else {
9078 if (list != NULL) {
9079 xmlNodePtr cur;
9080
9081 /*
9082 * Return the newly created nodeset after unlinking it from
9083 * they pseudo parent.
9084 */
9085 cur = newDoc->children->children;
9086 *list = cur;
9087 while (cur != NULL) {
9088 cur->parent = NULL;
9089 cur = cur->next;
9090 }
9091 newDoc->children->children = NULL;
9092 }
9093 ret = 0;
9094 }
9095 if (sax != NULL)
9096 ctxt->sax = oldsax;
9097 xmlFreeParserCtxt(ctxt);
9098 newDoc->intSubset = NULL;
9099 newDoc->extSubset = NULL;
9100 xmlFreeDoc(newDoc);
9101
9102 return(ret);
9103}
9104
9105/**
Daniel Veillardb1059e22000-09-16 14:02:43 +00009106 * xmlSAXParseEntity:
9107 * @sax: the SAX handler block
9108 * @filename: the filename
Daniel Veillard0142b842000-01-14 14:45:24 +00009109 *
Daniel Veillardb1059e22000-09-16 14:02:43 +00009110 * parse an XML external entity out of context and build a tree.
9111 * It use the given SAX function block to handle the parsing callback.
9112 * If sax is NULL, fallback to the default DOM tree building routines.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009113 *
Daniel Veillardb1059e22000-09-16 14:02:43 +00009114 * [78] extParsedEnt ::= TextDecl? content
9115 *
9116 * This correspond to a "Well Balanced" chunk
9117 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00009118 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009119 */
9120
Daniel Veillard1e346af1999-02-22 10:33:01 +00009121xmlDocPtr
Daniel Veillardb1059e22000-09-16 14:02:43 +00009122xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
9123 xmlDocPtr ret;
9124 xmlParserCtxtPtr ctxt;
9125 char *directory = NULL;
9126
9127 ctxt = xmlCreateFileParserCtxt(filename);
9128 if (ctxt == NULL) {
9129 return(NULL);
9130 }
9131 if (sax != NULL) {
9132 if (ctxt->sax != NULL)
9133 xmlFree(ctxt->sax);
9134 ctxt->sax = sax;
9135 ctxt->userData = NULL;
9136 }
9137
9138 if ((ctxt->directory == NULL) && (directory == NULL))
9139 directory = xmlParserGetDirectory(filename);
9140
9141 xmlParseExtParsedEnt(ctxt);
9142
9143 if (ctxt->wellFormed)
9144 ret = ctxt->myDoc;
9145 else {
9146 ret = NULL;
9147 xmlFreeDoc(ctxt->myDoc);
9148 ctxt->myDoc = NULL;
9149 }
9150 if (sax != NULL)
9151 ctxt->sax = NULL;
9152 xmlFreeParserCtxt(ctxt);
9153
9154 return(ret);
9155}
9156
9157/**
9158 * xmlParseEntity:
9159 * @filename: the filename
9160 *
9161 * parse an XML external entity out of context and build a tree.
9162 *
9163 * [78] extParsedEnt ::= TextDecl? content
9164 *
9165 * This correspond to a "Well Balanced" chunk
9166 *
9167 * Returns the resulting document tree
9168 */
9169
9170xmlDocPtr
9171xmlParseEntity(const char *filename) {
9172 return(xmlSAXParseEntity(NULL, filename));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009173}
9174
9175/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009176 * xmlCreateEntityParserCtxt:
9177 * @URL: the entity URL
9178 * @ID: the entity PUBLIC ID
9179 * @base: a posible base for the target URI
9180 *
9181 * Create a parser context for an external entity
9182 * Automatic support for ZLIB/Compress compressed document is provided
9183 * by default if found at compile-time.
9184 *
9185 * Returns the new parser context or NULL
9186 */
9187xmlParserCtxtPtr
9188xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
9189 const xmlChar *base) {
9190 xmlParserCtxtPtr ctxt;
9191 xmlParserInputPtr inputStream;
9192 char *directory = NULL;
Daniel Veillard87b95392000-08-12 21:12:04 +00009193 xmlChar *uri;
9194
Daniel Veillardcf461992000-03-14 18:30:20 +00009195 ctxt = xmlNewParserCtxt();
9196 if (ctxt == NULL) {
9197 return(NULL);
9198 }
9199
Daniel Veillard87b95392000-08-12 21:12:04 +00009200 uri = xmlBuildURI(URL, base);
9201
9202 if (uri == NULL) {
9203 inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
9204 if (inputStream == NULL) {
9205 xmlFreeParserCtxt(ctxt);
9206 return(NULL);
9207 }
9208
9209 inputPush(ctxt, inputStream);
9210
9211 if ((ctxt->directory == NULL) && (directory == NULL))
9212 directory = xmlParserGetDirectory((char *)URL);
9213 if ((ctxt->directory == NULL) && (directory != NULL))
9214 ctxt->directory = directory;
9215 } else {
9216 inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
9217 if (inputStream == NULL) {
9218 xmlFreeParserCtxt(ctxt);
9219 return(NULL);
9220 }
9221
9222 inputPush(ctxt, inputStream);
9223
9224 if ((ctxt->directory == NULL) && (directory == NULL))
9225 directory = xmlParserGetDirectory((char *)uri);
9226 if ((ctxt->directory == NULL) && (directory != NULL))
9227 ctxt->directory = directory;
9228 xmlFree(uri);
Daniel Veillardcf461992000-03-14 18:30:20 +00009229 }
9230
Daniel Veillardcf461992000-03-14 18:30:20 +00009231 return(ctxt);
9232}
9233
Daniel Veillardb1059e22000-09-16 14:02:43 +00009234/************************************************************************
9235 * *
9236 * Front ends when parsing from a file *
9237 * *
9238 ************************************************************************/
9239
Daniel Veillardcf461992000-03-14 18:30:20 +00009240/**
9241 * xmlCreateFileParserCtxt:
Daniel Veillard11e00581998-10-24 18:27:49 +00009242 * @filename: the filename
9243 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00009244 * Create a parser context for a file content.
9245 * Automatic support for ZLIB/Compress compressed document is provided
9246 * by default if found at compile-time.
Daniel Veillard11e00581998-10-24 18:27:49 +00009247 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00009248 * Returns the new parser context or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00009249 */
Daniel Veillardd692aa41999-02-28 21:54:31 +00009250xmlParserCtxtPtr
9251xmlCreateFileParserCtxt(const char *filename)
9252{
9253 xmlParserCtxtPtr ctxt;
Daniel Veillard260a68f1998-08-13 03:39:55 +00009254 xmlParserInputPtr inputStream;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00009255 xmlParserInputBufferPtr buf;
Daniel Veillardb05deb71999-08-10 19:04:08 +00009256 char *directory = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00009257
Daniel Veillarde2d034d1999-07-27 19:52:06 +00009258 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
Daniel Veillard39c7d712000-09-10 16:14:55 +00009259 if (buf == NULL) {
9260 return(NULL);
9261 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00009262
Daniel Veillardb05deb71999-08-10 19:04:08 +00009263 ctxt = xmlNewParserCtxt();
Daniel Veillard260a68f1998-08-13 03:39:55 +00009264 if (ctxt == NULL) {
Daniel Veillard39c7d712000-09-10 16:14:55 +00009265 if (xmlDefaultSAXHandler.error != NULL) {
9266 xmlDefaultSAXHandler.error(NULL, "out of memory\n");
9267 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00009268 return(NULL);
9269 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00009270
9271 inputStream = xmlNewInputStream(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009272 if (inputStream == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00009273 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009274 return(NULL);
9275 }
9276
Daniel Veillard6454aec1999-09-02 22:04:43 +00009277 inputStream->filename = xmlMemStrdup(filename);
Daniel Veillarde2d034d1999-07-27 19:52:06 +00009278 inputStream->buf = buf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00009279 inputStream->base = inputStream->buf->buffer->content;
9280 inputStream->cur = inputStream->buf->buffer->content;
Daniel Veillard260a68f1998-08-13 03:39:55 +00009281
9282 inputPush(ctxt, inputStream);
Daniel Veillardb05deb71999-08-10 19:04:08 +00009283 if ((ctxt->directory == NULL) && (directory == NULL))
9284 directory = xmlParserGetDirectory(filename);
9285 if ((ctxt->directory == NULL) && (directory != NULL))
9286 ctxt->directory = directory;
9287
Daniel Veillardd692aa41999-02-28 21:54:31 +00009288 return(ctxt);
9289}
9290
9291/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009292 * xmlSAXParseFile:
Daniel Veillardd692aa41999-02-28 21:54:31 +00009293 * @sax: the SAX handler block
9294 * @filename: the filename
9295 * @recovery: work in recovery mode, i.e. tries to read no Well Formed
9296 * documents
9297 *
9298 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9299 * compressed document is provided by default if found at compile-time.
9300 * It use the given SAX function block to handle the parsing callback.
9301 * If sax is NULL, fallback to the default DOM tree building routines.
9302 *
9303 * Returns the resulting document tree
9304 */
9305
Daniel Veillard011b63c1999-06-02 17:44:04 +00009306xmlDocPtr
9307xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
Daniel Veillardd692aa41999-02-28 21:54:31 +00009308 int recovery) {
9309 xmlDocPtr ret;
9310 xmlParserCtxtPtr ctxt;
Daniel Veillardb05deb71999-08-10 19:04:08 +00009311 char *directory = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00009312
9313 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard39c7d712000-09-10 16:14:55 +00009314 if (ctxt == NULL) {
9315 return(NULL);
9316 }
Daniel Veillard27d88741999-05-29 11:51:49 +00009317 if (sax != NULL) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00009318 if (ctxt->sax != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00009319 xmlFree(ctxt->sax);
Daniel Veillard27d88741999-05-29 11:51:49 +00009320 ctxt->sax = sax;
9321 ctxt->userData = NULL;
9322 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00009323
Daniel Veillardb05deb71999-08-10 19:04:08 +00009324 if ((ctxt->directory == NULL) && (directory == NULL))
9325 directory = xmlParserGetDirectory(filename);
9326 if ((ctxt->directory == NULL) && (directory != NULL))
Daniel Veillardcf461992000-03-14 18:30:20 +00009327 ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +00009328
Daniel Veillard260a68f1998-08-13 03:39:55 +00009329 xmlParseDocument(ctxt);
9330
Daniel Veillard517752b1999-04-05 12:20:10 +00009331 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009332 else {
9333 ret = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00009334 xmlFreeDoc(ctxt->myDoc);
9335 ctxt->myDoc = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009336 }
Daniel Veillard97fea181999-06-26 23:07:37 +00009337 if (sax != NULL)
9338 ctxt->sax = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00009339 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009340
9341 return(ret);
9342}
9343
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009344/**
Daniel Veillardb1059e22000-09-16 14:02:43 +00009345 * xmlRecoverDoc:
9346 * @cur: a pointer to an array of xmlChar
9347 *
9348 * parse an XML in-memory document and build a tree.
9349 * In the case the document is not Well Formed, a tree is built anyway
9350 *
9351 * Returns the resulting document tree
9352 */
9353
9354xmlDocPtr
9355xmlRecoverDoc(xmlChar *cur) {
9356 return(xmlSAXParseDoc(NULL, cur, 1));
9357}
9358
9359/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009360 * xmlParseFile:
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009361 * @filename: the filename
9362 *
9363 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9364 * compressed document is provided by default if found at compile-time.
9365 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00009366 * Returns the resulting document tree
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009367 */
9368
Daniel Veillard011b63c1999-06-02 17:44:04 +00009369xmlDocPtr
9370xmlParseFile(const char *filename) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009371 return(xmlSAXParseFile(NULL, filename, 0));
9372}
9373
9374/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009375 * xmlRecoverFile:
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009376 * @filename: the filename
9377 *
9378 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
9379 * compressed document is provided by default if found at compile-time.
9380 * In the case the document is not Well Formed, a tree is built anyway
9381 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00009382 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009383 */
9384
Daniel Veillard011b63c1999-06-02 17:44:04 +00009385xmlDocPtr
9386xmlRecoverFile(const char *filename) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009387 return(xmlSAXParseFile(NULL, filename, 1));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009388}
Daniel Veillard260a68f1998-08-13 03:39:55 +00009389
Daniel Veillardb1059e22000-09-16 14:02:43 +00009390
9391/**
9392 * xmlSetupParserForBuffer:
9393 * @ctxt: an XML parser context
9394 * @buffer: a xmlChar * buffer
9395 * @filename: a file name
9396 *
9397 * Setup the parser context to parse a new buffer; Clears any prior
9398 * contents from the parser context. The buffer parameter must not be
9399 * NULL, but the filename parameter can be
9400 */
9401void
9402xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
9403 const char* filename)
9404{
9405 xmlParserInputPtr input;
9406
9407 input = xmlNewInputStream(ctxt);
9408 if (input == NULL) {
9409 perror("malloc");
9410 xmlFree(ctxt);
9411 return;
9412 }
9413
9414 xmlClearParserCtxt(ctxt);
9415 if (filename != NULL)
9416 input->filename = xmlMemStrdup(filename);
9417 input->base = buffer;
9418 input->cur = buffer;
9419 inputPush(ctxt, input);
9420}
9421
9422/**
9423 * xmlSAXUserParseFile:
9424 * @sax: a SAX handler
9425 * @user_data: The user data returned on SAX callbacks
9426 * @filename: a file name
9427 *
9428 * parse an XML file and call the given SAX handler routines.
9429 * Automatic support for ZLIB/Compress compressed document is provided
9430 *
9431 * Returns 0 in case of success or a error number otherwise
9432 */
9433int
9434xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
9435 const char *filename) {
9436 int ret = 0;
9437 xmlParserCtxtPtr ctxt;
9438
9439 ctxt = xmlCreateFileParserCtxt(filename);
9440 if (ctxt == NULL) return -1;
9441 if (ctxt->sax != &xmlDefaultSAXHandler)
9442 xmlFree(ctxt->sax);
9443 ctxt->sax = sax;
9444 if (user_data != NULL)
9445 ctxt->userData = user_data;
9446
9447 xmlParseDocument(ctxt);
9448
9449 if (ctxt->wellFormed)
9450 ret = 0;
9451 else {
9452 if (ctxt->errNo != 0)
9453 ret = ctxt->errNo;
9454 else
9455 ret = -1;
9456 }
9457 if (sax != NULL)
9458 ctxt->sax = NULL;
9459 xmlFreeParserCtxt(ctxt);
9460
9461 return ret;
9462}
9463
9464/************************************************************************
9465 * *
9466 * Front ends when parsing from memory *
9467 * *
9468 ************************************************************************/
9469
Daniel Veillard11e00581998-10-24 18:27:49 +00009470/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009471 * xmlCreateMemoryParserCtxt:
Daniel Veillardb1059e22000-09-16 14:02:43 +00009472 * @buffer: a pointer to a char array
9473 * @size: the size of the array
Daniel Veillard11e00581998-10-24 18:27:49 +00009474 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00009475 * Create a parser context for an XML in-memory document.
Daniel Veillard11e00581998-10-24 18:27:49 +00009476 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00009477 * Returns the new parser context or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +00009478 */
Daniel Veillardd692aa41999-02-28 21:54:31 +00009479xmlParserCtxtPtr
9480xmlCreateMemoryParserCtxt(char *buffer, int size) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00009481 xmlParserCtxtPtr ctxt;
9482 xmlParserInputPtr input;
Daniel Veillard46e370e2000-07-21 20:32:03 +00009483 xmlParserInputBufferPtr buf;
Daniel Veillard260a68f1998-08-13 03:39:55 +00009484
Daniel Veillardb1059e22000-09-16 14:02:43 +00009485 if (buffer == NULL)
9486 return(NULL);
9487 if (size <= 0)
Daniel Veillardb566ce12000-03-04 11:39:42 +00009488 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009489
Daniel Veillardb05deb71999-08-10 19:04:08 +00009490 ctxt = xmlNewParserCtxt();
Daniel Veillardcf461992000-03-14 18:30:20 +00009491 if (ctxt == NULL)
Daniel Veillard260a68f1998-08-13 03:39:55 +00009492 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00009493
Daniel Veillard46e370e2000-07-21 20:32:03 +00009494 buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
9495 if (buf == NULL) return(NULL);
9496
Daniel Veillardb05deb71999-08-10 19:04:08 +00009497 input = xmlNewInputStream(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009498 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00009499 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009500 return(NULL);
9501 }
9502
9503 input->filename = NULL;
Daniel Veillard46e370e2000-07-21 20:32:03 +00009504 input->buf = buf;
9505 input->base = input->buf->buffer->content;
9506 input->cur = input->buf->buffer->content;
Daniel Veillard260a68f1998-08-13 03:39:55 +00009507
9508 inputPush(ctxt, input);
Daniel Veillardd692aa41999-02-28 21:54:31 +00009509 return(ctxt);
9510}
9511
9512/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009513 * xmlSAXParseMemory:
Daniel Veillardd692aa41999-02-28 21:54:31 +00009514 * @sax: the SAX handler block
9515 * @buffer: an pointer to a char array
Daniel Veillard51e3b151999-11-12 17:02:31 +00009516 * @size: the size of the array
9517 * @recovery: work in recovery mode, i.e. tries to read not Well Formed
Daniel Veillardd692aa41999-02-28 21:54:31 +00009518 * documents
9519 *
9520 * parse an XML in-memory block and use the given SAX function block
9521 * to handle the parsing callback. If sax is NULL, fallback to the default
9522 * DOM tree building routines.
9523 *
Daniel Veillardd692aa41999-02-28 21:54:31 +00009524 * Returns the resulting document tree
9525 */
9526xmlDocPtr
9527xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
9528 xmlDocPtr ret;
9529 xmlParserCtxtPtr ctxt;
9530
9531 ctxt = xmlCreateMemoryParserCtxt(buffer, size);
9532 if (ctxt == NULL) return(NULL);
Daniel Veillard27d88741999-05-29 11:51:49 +00009533 if (sax != NULL) {
9534 ctxt->sax = sax;
9535 ctxt->userData = NULL;
9536 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00009537
9538 xmlParseDocument(ctxt);
9539
Daniel Veillard517752b1999-04-05 12:20:10 +00009540 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009541 else {
9542 ret = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +00009543 xmlFreeDoc(ctxt->myDoc);
9544 ctxt->myDoc = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009545 }
Daniel Veillard97fea181999-06-26 23:07:37 +00009546 if (sax != NULL)
9547 ctxt->sax = NULL;
Daniel Veillardd692aa41999-02-28 21:54:31 +00009548 xmlFreeParserCtxt(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00009549
9550 return(ret);
9551}
9552
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009553/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009554 * xmlParseMemory:
Daniel Veillard1e346af1999-02-22 10:33:01 +00009555 * @buffer: an pointer to a char array
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009556 * @size: the size of the array
9557 *
9558 * parse an XML in-memory block and build a tree.
9559 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00009560 * Returns the resulting document tree
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009561 */
9562
9563xmlDocPtr xmlParseMemory(char *buffer, int size) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009564 return(xmlSAXParseMemory(NULL, buffer, size, 0));
9565}
9566
9567/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009568 * xmlRecoverMemory:
Daniel Veillard1e346af1999-02-22 10:33:01 +00009569 * @buffer: an pointer to a char array
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009570 * @size: the size of the array
9571 *
9572 * parse an XML in-memory block and build a tree.
9573 * In the case the document is not Well Formed, a tree is built anyway
9574 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00009575 * Returns the resulting document tree
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00009576 */
9577
9578xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
9579 return(xmlSAXParseMemory(NULL, buffer, size, 1));
Daniel Veillard42dc9b31998-11-09 01:17:21 +00009580}
Daniel Veillard260a68f1998-08-13 03:39:55 +00009581
Daniel Veillard7a66ee61999-09-26 11:31:02 +00009582/**
9583 * xmlSAXUserParseMemory:
9584 * @sax: a SAX handler
9585 * @user_data: The user data returned on SAX callbacks
9586 * @buffer: an in-memory XML document input
Daniel Veillard51e3b151999-11-12 17:02:31 +00009587 * @size: the length of the XML document in bytes
Daniel Veillard7a66ee61999-09-26 11:31:02 +00009588 *
9589 * A better SAX parsing routine.
9590 * parse an XML in-memory buffer and call the given SAX handler routines.
9591 *
9592 * Returns 0 in case of success or a error number otherwise
9593 */
9594int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
9595 char *buffer, int size) {
9596 int ret = 0;
9597 xmlParserCtxtPtr ctxt;
Daniel Veillard87b95392000-08-12 21:12:04 +00009598 xmlSAXHandlerPtr oldsax = NULL;
Daniel Veillard7a66ee61999-09-26 11:31:02 +00009599
9600 ctxt = xmlCreateMemoryParserCtxt(buffer, size);
9601 if (ctxt == NULL) return -1;
Daniel Veillard87b95392000-08-12 21:12:04 +00009602 if (sax != NULL) {
9603 oldsax = ctxt->sax;
9604 ctxt->sax = sax;
9605 }
Daniel Veillard7a66ee61999-09-26 11:31:02 +00009606 ctxt->userData = user_data;
9607
9608 xmlParseDocument(ctxt);
9609
9610 if (ctxt->wellFormed)
9611 ret = 0;
9612 else {
9613 if (ctxt->errNo != 0)
9614 ret = ctxt->errNo;
9615 else
9616 ret = -1;
9617 }
Daniel Veillard87b95392000-08-12 21:12:04 +00009618 if (sax != NULL) {
9619 ctxt->sax = oldsax;
9620 }
Daniel Veillard7a66ee61999-09-26 11:31:02 +00009621 xmlFreeParserCtxt(ctxt);
9622
9623 return ret;
9624}
9625
Daniel Veillardb1059e22000-09-16 14:02:43 +00009626/**
9627 * xmlCreateDocParserCtxt:
9628 * @cur: a pointer to an array of xmlChar
9629 *
9630 * Creates a parser context for an XML in-memory document.
9631 *
9632 * Returns the new parser context or NULL
9633 */
9634xmlParserCtxtPtr
9635xmlCreateDocParserCtxt(xmlChar *cur) {
9636 int len;
9637
9638 if (cur == NULL)
9639 return(NULL);
9640 len = xmlStrlen(cur);
9641 return(xmlCreateMemoryParserCtxt((char *)cur, len));
9642}
9643
9644/**
9645 * xmlSAXParseDoc:
9646 * @sax: the SAX handler block
9647 * @cur: a pointer to an array of xmlChar
9648 * @recovery: work in recovery mode, i.e. tries to read no Well Formed
9649 * documents
9650 *
9651 * parse an XML in-memory document and build a tree.
9652 * It use the given SAX function block to handle the parsing callback.
9653 * If sax is NULL, fallback to the default DOM tree building routines.
9654 *
9655 * Returns the resulting document tree
9656 */
9657
9658xmlDocPtr
9659xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
9660 xmlDocPtr ret;
9661 xmlParserCtxtPtr ctxt;
9662
9663 if (cur == NULL) return(NULL);
9664
9665
9666 ctxt = xmlCreateDocParserCtxt(cur);
9667 if (ctxt == NULL) return(NULL);
9668 if (sax != NULL) {
9669 ctxt->sax = sax;
9670 ctxt->userData = NULL;
9671 }
9672
9673 xmlParseDocument(ctxt);
9674 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
9675 else {
9676 ret = NULL;
9677 xmlFreeDoc(ctxt->myDoc);
9678 ctxt->myDoc = NULL;
9679 }
9680 if (sax != NULL)
9681 ctxt->sax = NULL;
9682 xmlFreeParserCtxt(ctxt);
9683
9684 return(ret);
9685}
9686
9687/**
9688 * xmlParseDoc:
9689 * @cur: a pointer to an array of xmlChar
9690 *
9691 * parse an XML in-memory document and build a tree.
9692 *
9693 * Returns the resulting document tree
9694 */
9695
9696xmlDocPtr
9697xmlParseDoc(xmlChar *cur) {
9698 return(xmlSAXParseDoc(NULL, cur, 0));
9699}
9700
Daniel Veillard260a68f1998-08-13 03:39:55 +00009701
Daniel Veillardb05deb71999-08-10 19:04:08 +00009702/************************************************************************
9703 * *
Daniel Veillard51e3b151999-11-12 17:02:31 +00009704 * Miscellaneous *
Daniel Veillardb05deb71999-08-10 19:04:08 +00009705 * *
9706 ************************************************************************/
9707
Daniel Veillard7cfce322000-10-04 12:40:27 +00009708#ifdef LIBXML_XPATH_ENABLED
9709#include <libxml/xpath.h>
9710#endif
9711
Daniel Veillardbc765302000-10-01 18:23:35 +00009712static int xmlParserInitialized = 0;
9713
9714/**
9715 * xmlInitParser:
9716 *
9717 * Initialization function for the XML parser.
9718 * This is not reentrant. Call once before processing in case of
9719 * use in multithreaded programs.
9720 */
9721
9722void
9723xmlInitParser(void) {
9724 if (xmlParserInitialized) return;
9725
9726 xmlInitCharEncodingHandlers();
9727 xmlInitializePredefinedEntities();
9728 xmlDefaultSAXHandlerInit();
Daniel Veillard7cfce322000-10-04 12:40:27 +00009729 xmlRegisterDefaultInputCallbacks();
9730 xmlRegisterDefaultOutputCallbacks();
Daniel Veillardbc765302000-10-01 18:23:35 +00009731#ifdef LIBXML_HTML_ENABLED
9732 htmlInitAutoClose();
9733 htmlDefaultSAXHandlerInit();
9734#endif
Daniel Veillard7cfce322000-10-04 12:40:27 +00009735#ifdef LIBXML_XPATH_ENABLED
9736 xmlXPathInit();
9737#endif
Daniel Veillardbc765302000-10-01 18:23:35 +00009738 xmlParserInitialized = 1;
9739}
9740
Daniel Veillarda819dac1999-11-24 18:04:22 +00009741/**
9742 * xmlCleanupParser:
9743 *
9744 * Cleanup function for the XML parser. It tries to reclaim all
9745 * parsing related global memory allocated for the parser processing.
9746 * It doesn't deallocate any document related memory. Calling this
9747 * function should not prevent reusing the parser.
9748 */
9749
9750void
9751xmlCleanupParser(void) {
Daniel Veillardbc765302000-10-01 18:23:35 +00009752 xmlParserInitialized = 0;
Daniel Veillarda819dac1999-11-24 18:04:22 +00009753 xmlCleanupCharEncodingHandlers();
Daniel Veillardf5c2c871999-12-01 09:51:45 +00009754 xmlCleanupPredefinedEntities();
Daniel Veillarda819dac1999-11-24 18:04:22 +00009755}
Daniel Veillardb05deb71999-08-10 19:04:08 +00009756
Daniel Veillard11e00581998-10-24 18:27:49 +00009757/**
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00009758 * xmlPedanticParserDefault:
9759 * @val: int 0 or 1
9760 *
9761 * Set and return the previous value for enabling pedantic warnings.
9762 *
9763 * Returns the last value for 0 for no substitution, 1 for substitution.
9764 */
9765
9766int
9767xmlPedanticParserDefault(int val) {
9768 int old = xmlPedanticParserDefaultValue;
9769
9770 xmlPedanticParserDefaultValue = val;
9771 return(old);
9772}
9773
9774/**
Daniel Veillardcf461992000-03-14 18:30:20 +00009775 * xmlSubstituteEntitiesDefault:
Daniel Veillardb05deb71999-08-10 19:04:08 +00009776 * @val: int 0 or 1
9777 *
9778 * Set and return the previous value for default entity support.
9779 * Initially the parser always keep entity references instead of substituting
9780 * entity values in the output. This function has to be used to change the
9781 * default parser behaviour
9782 * SAX::subtituteEntities() has to be used for changing that on a file by
9783 * file basis.
9784 *
9785 * Returns the last value for 0 for no substitution, 1 for substitution.
9786 */
9787
9788int
9789xmlSubstituteEntitiesDefault(int val) {
9790 int old = xmlSubstituteEntitiesDefaultValue;
9791
9792 xmlSubstituteEntitiesDefaultValue = val;
9793 return(old);
9794}
9795
Daniel Veillardfb76c402000-03-04 11:39:42 +00009796/**
9797 * xmlKeepBlanksDefault:
9798 * @val: int 0 or 1
9799 *
9800 * Set and return the previous value for default blanks text nodes support.
9801 * The 1.x version of the parser used an heuristic to try to detect
9802 * ignorable white spaces. As a result the SAX callback was generating
9803 * ignorableWhitespace() callbacks instead of characters() one, and when
9804 * using the DOM output text nodes containing those blanks were not generated.
9805 * The 2.x and later version will switch to the XML standard way and
9806 * ignorableWhitespace() are only generated when running the parser in
9807 * validating mode and when the current element doesn't allow CDATA or
9808 * mixed content.
9809 * This function is provided as a way to force the standard behaviour
9810 * on 1.X libs and to switch back to the old mode for compatibility when
9811 * running 1.X client code on 2.X . Upgrade of 1.X code should be done
9812 * by using xmlIsBlankNode() commodity function to detect the "empty"
9813 * nodes generated.
9814 * This value also affect autogeneration of indentation when saving code
9815 * if blanks sections are kept, indentation is not generated.
9816 *
9817 * Returns the last value for 0 for no substitution, 1 for substitution.
9818 */
9819
9820int
9821xmlKeepBlanksDefault(int val) {
9822 int old = xmlKeepBlanksDefaultValue;
9823
9824 xmlKeepBlanksDefaultValue = val;
9825 xmlIndentTreeOutput = !val;
9826 return(old);
9827}
9828