Bug Summary

File:parser.c
Location:line 4192, column 2
Description:Value stored to 'nbchar' is never read

Annotated Source Code

<
1/*
2 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3 * implemented on top of the SAX interfaces
4 *
5 * 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 *
13 * 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 miscellaneous 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 standalone functions using a preparsed
26 * document.
27 *
28 * See Copyright for the status of this software.
29 *
30 * daniel@veillard.com
31 */
32
33#define IN_LIBXML
34#include "libxml.h"
35
36#if defined(WIN32) && !defined (__CYGWIN__)
37#define XML_DIR_SEP'/' '\\'
38#else
39#define XML_DIR_SEP'/' '/'
40#endif
41
42#include <stdlib.h>
43#include <string.h>
44#include <stdarg.h>
45#include <libxml/xmlmemory.h>
46#include <libxml/threads.h>
47#include <libxml/globals.h>
48#include <libxml/tree.h>
49#include <libxml/parser.h>
50#include <libxml/parserInternals.h>
51#include <libxml/valid.h>
52#include <libxml/entities.h>
53#include <libxml/xmlerror.h>
54#include <libxml/encoding.h>
55#include <libxml/xmlIO.h>
56#include <libxml/uri.h>
57#ifdef LIBXML_CATALOG_ENABLED
58#include <libxml/catalog.h>
59#endif
60#ifdef LIBXML_SCHEMAS_ENABLED
61#include <libxml/xmlschemastypes.h>
62#include <libxml/relaxng.h>
63#endif
64#ifdef HAVE_CTYPE_H1
65#include <ctype.h>
66#endif
67#ifdef HAVE_STDLIB_H1
68#include <stdlib.h>
69#endif
70#ifdef HAVE_SYS_STAT_H1
71#include <sys/stat.h>
72#endif
73#ifdef HAVE_FCNTL_H1
74#include <fcntl.h>
75#endif
76#ifdef HAVE_UNISTD_H1
77#include <unistd.h>
78#endif
79#ifdef HAVE_ZLIB_H1
80#include <zlib.h>
81#endif
82
83static void
84xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
85
86static xmlParserCtxtPtr
87xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
88 const xmlChar *base, xmlParserCtxtPtr pctx);
89
90/************************************************************************
91 * *
92 * Arbitrary limits set in the parser. See XML_PARSE_HUGE *
93 * *
94 ************************************************************************/
95
96#define XML_PARSER_BIG_ENTITY1000 1000
97#define XML_PARSER_LOT_ENTITY5000 5000
98
99/*
100 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
101 * replacement over the size in byte of the input indicates that you have
102 * and eponential behaviour. A value of 10 correspond to at least 3 entity
103 * replacement per byte of input.
104 */
105#define XML_PARSER_NON_LINEAR10 10
106
107/*
108 * xmlParserEntityCheck
109 *
110 * Function to check non-linear entity expansion behaviour
111 * This is here to detect and stop exponential linear entity expansion
112 * This is not a limitation of the parser but a safety
113 * boundary feature. It can be disabled with the XML_PARSE_HUGE
114 * parser option.
115 */
116static int
117xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
118 xmlEntityPtr ent)
119{
120 unsigned long consumed = 0;
121
122 if ((ctxt == NULL((void*)0)) || (ctxt->options & XML_PARSE_HUGE))
123 return (0);
124 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
125 return (1);
126 if (size != 0) {
127 /*
128 * Do the check based on the replacement size of the entity
129 */
130 if (size < XML_PARSER_BIG_ENTITY1000)
131 return(0);
132
133 /*
134 * A limit on the amount of text data reasonably used
135 */
136 if (ctxt->input != NULL((void*)0)) {
137 consumed = ctxt->input->consumed +
138 (ctxt->input->cur - ctxt->input->base);
139 }
140 consumed += ctxt->sizeentities;
141
142 if ((size < XML_PARSER_NON_LINEAR10 * consumed) &&
143 (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR10 * consumed))
144 return (0);
145 } else if (ent != NULL((void*)0)) {
146 /*
147 * use the number of parsed entities in the replacement
148 */
149 size = ent->checked;
150
151 /*
152 * The amount of data parsed counting entities size only once
153 */
154 if (ctxt->input != NULL((void*)0)) {
155 consumed = ctxt->input->consumed +
156 (ctxt->input->cur - ctxt->input->base);
157 }
158 consumed += ctxt->sizeentities;
159
160 /*
161 * Check the density of entities for the amount of data
162 * knowing an entity reference will take at least 3 bytes
163 */
164 if (size * 3 < consumed * XML_PARSER_NON_LINEAR10)
165 return (0);
166 } else {
167 /*
168 * strange we got no data for checking just return
169 */
170 return (0);
171 }
172
173 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL((void*)0));
174 return (1);
175}
176
177/**
178 * xmlParserMaxDepth:
179 *
180 * arbitrary depth limit for the XML documents that we allow to
181 * process. This is not a limitation of the parser but a safety
182 * boundary feature. It can be disabled with the XML_PARSE_HUGE
183 * parser option.
184 */
185unsigned int xmlParserMaxDepth = 256;
186
187
188
189#define SAX21 1
190#define XML_PARSER_BIG_BUFFER_SIZE300 300
191#define XML_PARSER_BUFFER_SIZE100 100
192#define SAX_COMPAT_MODE(xmlChar *) "SAX compatibility mode document" BAD_CAST(xmlChar *) "SAX compatibility mode document"
193
194/*
195 * List of XML prefixed PI allowed by W3C specs
196 */
197
198static const char *xmlW3CPIs[] = {
199 "xml-stylesheet",
200 NULL((void*)0)
201};
202
203
204/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
205static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
206 const xmlChar **str);
207
208static xmlParserErrors
209xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
210 xmlSAXHandlerPtr sax,
211 void *user_data, int depth, const xmlChar *URL,
212 const xmlChar *ID, xmlNodePtr *list);
213
214static int
215xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
216 const char *encoding);
217#ifdef LIBXML_LEGACY_ENABLED
218static void
219xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
220 xmlNodePtr lastNode);
221#endif /* LIBXML_LEGACY_ENABLED */
222
223static xmlParserErrors
224xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
225 const xmlChar *string, void *user_data, xmlNodePtr *lst);
226
227static int
228xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
229
230/************************************************************************
231 * *
232 * Some factorized error routines *
233 * *
234 ************************************************************************/
235
236/**
237 * xmlErrAttributeDup:
238 * @ctxt: an XML parser context
239 * @prefix: the attribute prefix
240 * @localname: the attribute localname
241 *
242 * Handle a redefinition of attribute error
243 */
244static void
245xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
246 const xmlChar * localname)
247{
248 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
249 (ctxt->instate == XML_PARSER_EOF))
250 return;
251 if (ctxt != NULL((void*)0))
252 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
253 if (prefix == NULL((void*)0))
254 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_PARSER,
255 ctxt->errNo, XML_ERR_FATAL, NULL((void*)0), 0,
256 (const char *) localname, NULL((void*)0), NULL((void*)0), 0, 0,
257 "Attribute %s redefined\n", localname);
258 else
259 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_PARSER,
260 ctxt->errNo, XML_ERR_FATAL, NULL((void*)0), 0,
261 (const char *) prefix, (const char *) localname,
262 NULL((void*)0), 0, 0, "Attribute %s:%s redefined\n", prefix,
263 localname);
264 if (ctxt != NULL((void*)0)) {
265 ctxt->wellFormed = 0;
266 if (ctxt->recovery == 0)
267 ctxt->disableSAX = 1;
268 }
269}
270
271/**
272 * xmlFatalErr:
273 * @ctxt: an XML parser context
274 * @error: the error number
275 * @extra: extra information string
276 *
277 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
278 */
279static void
280xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
281{
282 const char *errmsg;
283
284 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
285 (ctxt->instate == XML_PARSER_EOF))
286 return;
287 switch (error) {
288 case XML_ERR_INVALID_HEX_CHARREF:
289 errmsg = "CharRef: invalid hexadecimal value\n";
290 break;
291 case XML_ERR_INVALID_DEC_CHARREF:
292 errmsg = "CharRef: invalid decimal value\n";
293 break;
294 case XML_ERR_INVALID_CHARREF:
295 errmsg = "CharRef: invalid value\n";
296 break;
297 case XML_ERR_INTERNAL_ERROR:
298 errmsg = "internal error";
299 break;
300 case XML_ERR_PEREF_AT_EOF:
301 errmsg = "PEReference at end of document\n";
302 break;
303 case XML_ERR_PEREF_IN_PROLOG:
304 errmsg = "PEReference in prolog\n";
305 break;
306 case XML_ERR_PEREF_IN_EPILOG:
307 errmsg = "PEReference in epilog\n";
308 break;
309 case XML_ERR_PEREF_NO_NAME:
310 errmsg = "PEReference: no name\n";
311 break;
312 case XML_ERR_PEREF_SEMICOL_MISSING:
313 errmsg = "PEReference: expecting ';'\n";
314 break;
315 case XML_ERR_ENTITY_LOOP:
316 errmsg = "Detected an entity reference loop\n";
317 break;
318 case XML_ERR_ENTITY_NOT_STARTED:
319 errmsg = "EntityValue: \" or ' expected\n";
320 break;
321 case XML_ERR_ENTITY_PE_INTERNAL:
322 errmsg = "PEReferences forbidden in internal subset\n";
323 break;
324 case XML_ERR_ENTITY_NOT_FINISHED:
325 errmsg = "EntityValue: \" or ' expected\n";
326 break;
327 case XML_ERR_ATTRIBUTE_NOT_STARTED:
328 errmsg = "AttValue: \" or ' expected\n";
329 break;
330 case XML_ERR_LT_IN_ATTRIBUTE:
331 errmsg = "Unescaped '<' not allowed in attributes values\n";
332 break;
333 case XML_ERR_LITERAL_NOT_STARTED:
334 errmsg = "SystemLiteral \" or ' expected\n";
335 break;
336 case XML_ERR_LITERAL_NOT_FINISHED:
337 errmsg = "Unfinished System or Public ID \" or ' expected\n";
338 break;
339 case XML_ERR_MISPLACED_CDATA_END:
340 errmsg = "Sequence ']]>' not allowed in content\n";
341 break;
342 case XML_ERR_URI_REQUIRED:
343 errmsg = "SYSTEM or PUBLIC, the URI is missing\n";
344 break;
345 case XML_ERR_PUBID_REQUIRED:
346 errmsg = "PUBLIC, the Public Identifier is missing\n";
347 break;
348 case XML_ERR_HYPHEN_IN_COMMENT:
349 errmsg = "Comment must not contain '--' (double-hyphen)\n";
350 break;
351 case XML_ERR_PI_NOT_STARTED:
352 errmsg = "xmlParsePI : no target name\n";
353 break;
354 case XML_ERR_RESERVED_XML_NAME:
355 errmsg = "Invalid PI name\n";
356 break;
357 case XML_ERR_NOTATION_NOT_STARTED:
358 errmsg = "NOTATION: Name expected here\n";
359 break;
360 case XML_ERR_NOTATION_NOT_FINISHED:
361 errmsg = "'>' required to close NOTATION declaration\n";
362 break;
363 case XML_ERR_VALUE_REQUIRED:
364 errmsg = "Entity value required\n";
365 break;
366 case XML_ERR_URI_FRAGMENT:
367 errmsg = "Fragment not allowed";
368 break;
369 case XML_ERR_ATTLIST_NOT_STARTED:
370 errmsg = "'(' required to start ATTLIST enumeration\n";
371 break;
372 case XML_ERR_NMTOKEN_REQUIRED:
373 errmsg = "NmToken expected in ATTLIST enumeration\n";
374 break;
375 case XML_ERR_ATTLIST_NOT_FINISHED:
376 errmsg = "')' required to finish ATTLIST enumeration\n";
377 break;
378 case XML_ERR_MIXED_NOT_STARTED:
379 errmsg = "MixedContentDecl : '|' or ')*' expected\n";
380 break;
381 case XML_ERR_PCDATA_REQUIRED:
382 errmsg = "MixedContentDecl : '#PCDATA' expected\n";
383 break;
384 case XML_ERR_ELEMCONTENT_NOT_STARTED:
385 errmsg = "ContentDecl : Name or '(' expected\n";
386 break;
387 case XML_ERR_ELEMCONTENT_NOT_FINISHED:
388 errmsg = "ContentDecl : ',' '|' or ')' expected\n";
389 break;
390 case XML_ERR_PEREF_IN_INT_SUBSET:
391 errmsg =
392 "PEReference: forbidden within markup decl in internal subset\n";
393 break;
394 case XML_ERR_GT_REQUIRED:
395 errmsg = "expected '>'\n";
396 break;
397 case XML_ERR_CONDSEC_INVALID:
398 errmsg = "XML conditional section '[' expected\n";
399 break;
400 case XML_ERR_EXT_SUBSET_NOT_FINISHED:
401 errmsg = "Content error in the external subset\n";
402 break;
403 case XML_ERR_CONDSEC_INVALID_KEYWORD:
404 errmsg =
405 "conditional section INCLUDE or IGNORE keyword expected\n";
406 break;
407 case XML_ERR_CONDSEC_NOT_FINISHED:
408 errmsg = "XML conditional section not closed\n";
409 break;
410 case XML_ERR_XMLDECL_NOT_STARTED:
411 errmsg = "Text declaration '<?xml' required\n";
412 break;
413 case XML_ERR_XMLDECL_NOT_FINISHED:
414 errmsg = "parsing XML declaration: '?>' expected\n";
415 break;
416 case XML_ERR_EXT_ENTITY_STANDALONE:
417 errmsg = "external parsed entities cannot be standalone\n";
418 break;
419 case XML_ERR_ENTITYREF_SEMICOL_MISSING:
420 errmsg = "EntityRef: expecting ';'\n";
421 break;
422 case XML_ERR_DOCTYPE_NOT_FINISHED:
423 errmsg = "DOCTYPE improperly terminated\n";
424 break;
425 case XML_ERR_LTSLASH_REQUIRED:
426 errmsg = "EndTag: '</' not found\n";
427 break;
428 case XML_ERR_EQUAL_REQUIRED:
429 errmsg = "expected '='\n";
430 break;
431 case XML_ERR_STRING_NOT_CLOSED:
432 errmsg = "String not closed expecting \" or '\n";
433 break;
434 case XML_ERR_STRING_NOT_STARTED:
435 errmsg = "String not started expecting ' or \"\n";
436 break;
437 case XML_ERR_ENCODING_NAME:
438 errmsg = "Invalid XML encoding name\n";
439 break;
440 case XML_ERR_STANDALONE_VALUE:
441 errmsg = "standalone accepts only 'yes' or 'no'\n";
442 break;
443 case XML_ERR_DOCUMENT_EMPTY:
444 errmsg = "Document is empty\n";
445 break;
446 case XML_ERR_DOCUMENT_END:
447 errmsg = "Extra content at the end of the document\n";
448 break;
449 case XML_ERR_NOT_WELL_BALANCED:
450 errmsg = "chunk is not well balanced\n";
451 break;
452 case XML_ERR_EXTRA_CONTENT:
453 errmsg = "extra content at the end of well balanced chunk\n";
454 break;
455 case XML_ERR_VERSION_MISSING:
456 errmsg = "Malformed declaration expecting version\n";
457 break;
458#if 0
459 case:
460 errmsg = "\n";
461 break;
462#endif
463 default:
464 errmsg = "Unregistered error message\n";
465 }
466 if (ctxt != NULL((void*)0))
467 ctxt->errNo = error;
468 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_PARSER, error,
469 XML_ERR_FATAL, NULL((void*)0), 0, info, NULL((void*)0), NULL((void*)0), 0, 0, errmsg,
470 info);
471 if (ctxt != NULL((void*)0)) {
472 ctxt->wellFormed = 0;
473 if (ctxt->recovery == 0)
474 ctxt->disableSAX = 1;
475 }
476}
477
478/**
479 * xmlFatalErrMsg:
480 * @ctxt: an XML parser context
481 * @error: the error number
482 * @msg: the error message
483 *
484 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
485 */
486static void
487xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
488 const char *msg)
489{
490 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
491 (ctxt->instate == XML_PARSER_EOF))
492 return;
493 if (ctxt != NULL((void*)0))
494 ctxt->errNo = error;
495 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_PARSER, error,
496 XML_ERR_FATAL, NULL((void*)0), 0, NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, 0, "%s", msg);
497 if (ctxt != NULL((void*)0)) {
498 ctxt->wellFormed = 0;
499 if (ctxt->recovery == 0)
500 ctxt->disableSAX = 1;
501 }
502}
503
504/**
505 * xmlWarningMsg:
506 * @ctxt: an XML parser context
507 * @error: the error number
508 * @msg: the error message
509 * @str1: extra data
510 * @str2: extra data
511 *
512 * Handle a warning.
513 */
514static void
515xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
516 const char *msg, const xmlChar *str1, const xmlChar *str2)
517{
518 xmlStructuredErrorFunc schannel = NULL((void*)0);
519
520 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
521 (ctxt->instate == XML_PARSER_EOF))
522 return;
523 if ((ctxt != NULL((void*)0)) && (ctxt->sax != NULL((void*)0)) &&
524 (ctxt->sax->initialized == XML_SAX2_MAGIC0xDEEDBEAF))
525 schannel = ctxt->sax->serror;
526 __xmlRaiseError(schannel,
527 (ctxt->sax) ? ctxt->sax->warning : NULL((void*)0),
528 ctxt->userData,
529 ctxt, NULL((void*)0), XML_FROM_PARSER, error,
530 XML_ERR_WARNING, NULL((void*)0), 0,
531 (const char *) str1, (const char *) str2, NULL((void*)0), 0, 0,
532 msg, (const char *) str1, (const char *) str2);
533}
534
535/**
536 * xmlValidityError:
537 * @ctxt: an XML parser context
538 * @error: the error number
539 * @msg: the error message
540 * @str1: extra data
541 *
542 * Handle a validity error.
543 */
544static void
545xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
546 const char *msg, const xmlChar *str1, const xmlChar *str2)
547{
548 xmlStructuredErrorFunc schannel = NULL((void*)0);
549
550 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
551 (ctxt->instate == XML_PARSER_EOF))
552 return;
553 if (ctxt != NULL((void*)0)) {
554 ctxt->errNo = error;
555 if ((ctxt->sax != NULL((void*)0)) && (ctxt->sax->initialized == XML_SAX2_MAGIC0xDEEDBEAF))
556 schannel = ctxt->sax->serror;
557 }
558 __xmlRaiseError(schannel,
559 ctxt->vctxt.error, ctxt->vctxt.userData,
560 ctxt, NULL((void*)0), XML_FROM_DTD, error,
561 XML_ERR_ERROR, NULL((void*)0), 0, (const char *) str1,
562 (const char *) str2, NULL((void*)0), 0, 0,
563 msg, (const char *) str1, (const char *) str2);
564 if (ctxt != NULL((void*)0)) {
565 ctxt->valid = 0;
566 }
567}
568
569/**
570 * xmlFatalErrMsgInt:
571 * @ctxt: an XML parser context
572 * @error: the error number
573 * @msg: the error message
574 * @val: an integer value
575 *
576 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
577 */
578static void
579xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
580 const char *msg, int val)
581{
582 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
583 (ctxt->instate == XML_PARSER_EOF))
584 return;
585 if (ctxt != NULL((void*)0))
586 ctxt->errNo = error;
587 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0),
588 ctxt, NULL((void*)0), XML_FROM_PARSER, error, XML_ERR_FATAL,
589 NULL((void*)0), 0, NULL((void*)0), NULL((void*)0), NULL((void*)0), val, 0, msg, val);
590 if (ctxt != NULL((void*)0)) {
591 ctxt->wellFormed = 0;
592 if (ctxt->recovery == 0)
593 ctxt->disableSAX = 1;
594 }
595}
596
597/**
598 * xmlFatalErrMsgStrIntStr:
599 * @ctxt: an XML parser context
600 * @error: the error number
601 * @msg: the error message
602 * @str1: an string info
603 * @val: an integer value
604 * @str2: an string info
605 *
606 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
607 */
608static void
609xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
610 const char *msg, const xmlChar *str1, int val,
611 const xmlChar *str2)
612{
613 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
614 (ctxt->instate == XML_PARSER_EOF))
615 return;
616 if (ctxt != NULL((void*)0))
617 ctxt->errNo = error;
618 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0),
619 ctxt, NULL((void*)0), XML_FROM_PARSER, error, XML_ERR_FATAL,
620 NULL((void*)0), 0, (const char *) str1, (const char *) str2,
621 NULL((void*)0), val, 0, msg, str1, val, str2);
622 if (ctxt != NULL((void*)0)) {
623 ctxt->wellFormed = 0;
624 if (ctxt->recovery == 0)
625 ctxt->disableSAX = 1;
626 }
627}
628
629/**
630 * xmlFatalErrMsgStr:
631 * @ctxt: an XML parser context
632 * @error: the error number
633 * @msg: the error message
634 * @val: a string value
635 *
636 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
637 */
638static void
639xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
640 const char *msg, const xmlChar * val)
641{
642 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
643 (ctxt->instate == XML_PARSER_EOF))
644 return;
645 if (ctxt != NULL((void*)0))
646 ctxt->errNo = error;
647 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0),
648 XML_FROM_PARSER, error, XML_ERR_FATAL,
649 NULL((void*)0), 0, (const char *) val, NULL((void*)0), NULL((void*)0), 0, 0, msg,
650 val);
651 if (ctxt != NULL((void*)0)) {
652 ctxt->wellFormed = 0;
653 if (ctxt->recovery == 0)
654 ctxt->disableSAX = 1;
655 }
656}
657
658/**
659 * xmlErrMsgStr:
660 * @ctxt: an XML parser context
661 * @error: the error number
662 * @msg: the error message
663 * @val: a string value
664 *
665 * Handle a non fatal parser error
666 */
667static void
668xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
669 const char *msg, const xmlChar * val)
670{
671 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
672 (ctxt->instate == XML_PARSER_EOF))
673 return;
674 if (ctxt != NULL((void*)0))
675 ctxt->errNo = error;
676 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0),
677 XML_FROM_PARSER, error, XML_ERR_ERROR,
678 NULL((void*)0), 0, (const char *) val, NULL((void*)0), NULL((void*)0), 0, 0, msg,
679 val);
680}
681
682/**
683 * xmlNsErr:
684 * @ctxt: an XML parser context
685 * @error: the error number
686 * @msg: the message
687 * @info1: extra information string
688 * @info2: extra information string
689 *
690 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
691 */
692static void
693xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
694 const char *msg,
695 const xmlChar * info1, const xmlChar * info2,
696 const xmlChar * info3)
697{
698 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
699 (ctxt->instate == XML_PARSER_EOF))
700 return;
701 if (ctxt != NULL((void*)0))
702 ctxt->errNo = error;
703 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_NAMESPACE, error,
704 XML_ERR_ERROR, NULL((void*)0), 0, (const char *) info1,
705 (const char *) info2, (const char *) info3, 0, 0, msg,
706 info1, info2, info3);
707 if (ctxt != NULL((void*)0))
708 ctxt->nsWellFormed = 0;
709}
710
711/**
712 * xmlNsWarn
713 * @ctxt: an XML parser context
714 * @error: the error number
715 * @msg: the message
716 * @info1: extra information string
717 * @info2: extra information string
718 *
719 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
720 */
721static void
722xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
723 const char *msg,
724 const xmlChar * info1, const xmlChar * info2,
725 const xmlChar * info3)
726{
727 if ((ctxt != NULL((void*)0)) && (ctxt->disableSAX != 0) &&
728 (ctxt->instate == XML_PARSER_EOF))
729 return;
730 __xmlRaiseError(NULL((void*)0), NULL((void*)0), NULL((void*)0), ctxt, NULL((void*)0), XML_FROM_NAMESPACE, error,
731 XML_ERR_WARNING, NULL((void*)0), 0, (const char *) info1,
732 (const char *) info2, (const char *) info3, 0, 0, msg,
733 info1, info2, info3);
734}
735
736/************************************************************************
737 * *
738 * Library wide options *
739 * *
740 ************************************************************************/
741
742/**
743 * xmlHasFeature:
744 * @feature: the feature to be examined
745 *
746 * Examines if the library has been compiled with a given feature.
747 *
748 * Returns a non-zero value if the feature exist, otherwise zero.
749 * Returns zero (0) if the feature does not exist or an unknown
750 * unknown feature is requested, non-zero otherwise.
751 */
752int
753xmlHasFeature(xmlFeature feature)
754{
755 switch (feature) {
756 case XML_WITH_THREAD:
757#ifdef LIBXML_THREAD_ENABLED
758 return(1);
759#else
760 return(0);
761#endif
762 case XML_WITH_TREE:
763#ifdef LIBXML_TREE_ENABLED
764 return(1);
765#else
766 return(0);
767#endif
768 case XML_WITH_OUTPUT:
769#ifdef LIBXML_OUTPUT_ENABLED
770 return(1);
771#else
772 return(0);
773#endif
774 case XML_WITH_PUSH:
775#ifdef LIBXML_PUSH_ENABLED
776 return(1);
777#else
778 return(0);
779#endif
780 case XML_WITH_READER:
781#ifdef LIBXML_READER_ENABLED
782 return(1);
783#else
784 return(0);
785#endif
786 case XML_WITH_PATTERN:
787#ifdef LIBXML_PATTERN_ENABLED
788 return(1);
789#else
790 return(0);
791#endif
792 case XML_WITH_WRITER:
793#ifdef LIBXML_WRITER_ENABLED
794 return(1);
795#else
796 return(0);
797#endif
798 case XML_WITH_SAX1:
799#ifdef LIBXML_SAX1_ENABLED
800 return(1);
801#else
802 return(0);
803#endif
804 case XML_WITH_FTP:
805#ifdef LIBXML_FTP_ENABLED
806 return(1);
807#else
808 return(0);
809#endif
810 case XML_WITH_HTTP:
811#ifdef LIBXML_HTTP_ENABLED
812 return(1);
813#else
814 return(0);
815#endif
816 case XML_WITH_VALID:
817#ifdef LIBXML_VALID_ENABLED
818 return(1);
819#else
820 return(0);
821#endif
822 case XML_WITH_HTML:
823#ifdef LIBXML_HTML_ENABLED
824 return(1);
825#else
826 return(0);
827#endif
828 case XML_WITH_LEGACY:
829#ifdef LIBXML_LEGACY_ENABLED
830 return(1);
831#else
832 return(0);
833#endif
834 case XML_WITH_C14N:
835#ifdef LIBXML_C14N_ENABLED
836 return(1);
837#else
838 return(0);
839#endif
840 case XML_WITH_CATALOG:
841#ifdef LIBXML_CATALOG_ENABLED
842 return(1);
843#else
844 return(0);
845#endif
846 case XML_WITH_XPATH:
847#ifdef LIBXML_XPATH_ENABLED
848 return(1);
849#else
850 return(0);
851#endif
852 case XML_WITH_XPTR:
853#ifdef LIBXML_XPTR_ENABLED
854 return(1);
855#else
856 return(0);
857#endif
858 case XML_WITH_XINCLUDE:
859#ifdef LIBXML_XINCLUDE_ENABLED
860 return(1);
861#else
862 return(0);
863#endif
864 case XML_WITH_ICONV:
865#ifdef LIBXML_ICONV_ENABLED
866 return(1);
867#else
868 return(0);
869#endif
870 case XML_WITH_ISO8859X:
871#ifdef LIBXML_ISO8859X_ENABLED
872 return(1);
873#else
874 return(0);
875#endif
876 case XML_WITH_UNICODE:
877#ifdef LIBXML_UNICODE_ENABLED
878 return(1);
879#else
880 return(0);
881#endif
882 case XML_WITH_REGEXP:
883#ifdef LIBXML_REGEXP_ENABLED
884 return(1);
885#else
886 return(0);
887#endif
888 case XML_WITH_AUTOMATA:
889#ifdef LIBXML_AUTOMATA_ENABLED
890 return(1);
891#else
892 return(0);
893#endif
894 case XML_WITH_EXPR:
895#ifdef LIBXML_EXPR_ENABLED
896 return(1);
897#else
898 return(0);
899#endif
900 case XML_WITH_SCHEMAS:
901#ifdef LIBXML_SCHEMAS_ENABLED
902 return(1);
903#else
904 return(0);
905#endif
906 case XML_WITH_SCHEMATRON:
907#ifdef LIBXML_SCHEMATRON_ENABLED
908 return(1);
909#else
910 return(0);
911#endif
912 case XML_WITH_MODULES:
913#ifdef LIBXML_MODULES_ENABLED
914 return(1);
915#else
916 return(0);
917#endif
918 case XML_WITH_DEBUG:
919#ifdef LIBXML_DEBUG_ENABLED
920 return(1);
921#else
922 return(0);
923#endif
924 case XML_WITH_DEBUG_MEM:
925#ifdef DEBUG_MEMORY_LOCATION
926 return(1);
927#else
928 return(0);
929#endif
930 case XML_WITH_DEBUG_RUN:
931#ifdef LIBXML_DEBUG_RUNTIME
932 return(1);
933#else
934 return(0);
935#endif
936 case XML_WITH_ZLIB:
937#ifdef LIBXML_ZLIB_ENABLED
938 return(1);
939#else
940 return(0);
941#endif
942 default:
943 break;
944 }
945 return(0);
946}
947
948/************************************************************************
949 * *
950 * SAX2 defaulted attributes handling *
951 * *
952 ************************************************************************/
953
954/**
955 * xmlDetectSAX2:
956 * @ctxt: an XML parser context
957 *
958 * Do the SAX2 detection and specific intialization
959 */
960static void
961xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
962 if (ctxt == NULL((void*)0)) return;
963#ifdef LIBXML_SAX1_ENABLED
964 if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC0xDEEDBEAF) &&
965 ((ctxt->sax->startElementNs != NULL((void*)0)) ||
966 (ctxt->sax->endElementNs != NULL((void*)0)))) ctxt->sax2 = 1;
967#else
968 ctxt->sax2 = 1;
969#endif /* LIBXML_SAX1_ENABLED */
970
971 ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST(xmlChar *) "xml", 3);
972 ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST(xmlChar *) "xmlns", 5);
973 ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE(const xmlChar *) "http://www.w3.org/XML/1998/namespace", 36);
974 if ((ctxt->str_xml==NULL((void*)0)) || (ctxt->str_xmlns==NULL((void*)0)) ||
975 (ctxt->str_xml_ns == NULL((void*)0))) {
976 xmlErrMemory(ctxt, NULL((void*)0));
977 }
978}
979
980typedef struct _xmlDefAttrs xmlDefAttrs;
981typedef xmlDefAttrs *xmlDefAttrsPtr;
982struct _xmlDefAttrs {
983 int nbAttrs; /* number of defaulted attributes on that element */
984 int maxAttrs; /* the size of the array */
985 const xmlChar *values[5]; /* array of localname/prefix/values/external */
986};
987
988/**
989 * xmlAttrNormalizeSpace:
990 * @src: the source string
991 * @dst: the target string
992 *
993 * Normalize the space in non CDATA attribute values:
994 * If the attribute type is not CDATA, then the XML processor MUST further
995 * process the normalized attribute value by discarding any leading and
996 * trailing space (#x20) characters, and by replacing sequences of space
997 * (#x20) characters by a single space (#x20) character.
998 * Note that the size of dst need to be at least src, and if one doesn't need
999 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1000 * passing src as dst is just fine.
1001 *
1002 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1003 * is needed.
1004 */
1005static xmlChar *
1006xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1007{
1008 if ((src == NULL((void*)0)) || (dst == NULL((void*)0)))
1009 return(NULL((void*)0));
1010
1011 while (*src == 0x20) src++;
1012 while (*src != 0) {
1013 if (*src == 0x20) {
1014 while (*src == 0x20) src++;
1015 if (*src != 0)
1016 *dst++ = 0x20;
1017 } else {
1018 *dst++ = *src++;
1019 }
1020 }
1021 *dst = 0;
1022 if (dst == src)
1023 return(NULL((void*)0));
1024 return(dst);
1025}
1026
1027/**
1028 * xmlAttrNormalizeSpace2:
1029 * @src: the source string
1030 *
1031 * Normalize the space in non CDATA attribute values, a slightly more complex
1032 * front end to avoid allocation problems when running on attribute values
1033 * coming from the input.
1034 *
1035 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1036 * is needed.
1037 */
1038static const xmlChar *
1039xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1040{
1041 int i;
1042 int remove_head = 0;
1043 int need_realloc = 0;
1044 const xmlChar *cur;
1045
1046 if ((ctxt == NULL((void*)0)) || (src == NULL((void*)0)) || (len == NULL((void*)0)))
1047 return(NULL((void*)0));
1048 i = *len;
1049 if (i <= 0)
1050 return(NULL((void*)0));
1051
1052 cur = src;
1053 while (*cur == 0x20) {
1054 cur++;
1055 remove_head++;
1056 }
1057 while (*cur != 0) {
1058 if (*cur == 0x20) {
1059 cur++;
1060 if ((*cur == 0x20) || (*cur == 0)) {
1061 need_realloc = 1;
1062 break;
1063 }
1064 } else
1065 cur++;
1066 }
1067 if (need_realloc) {
1068 xmlChar *ret;
1069
1070 ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1071 if (ret == NULL((void*)0)) {
1072 xmlErrMemory(ctxt, NULL((void*)0));
1073 return(NULL((void*)0));
1074 }
1075 xmlAttrNormalizeSpace(ret, ret);
1076 *len = (int) strlen((const char *)ret);
1077 return(ret);
1078 } else if (remove_head) {
1079 *len -= remove_head;
1080 memmove(src, src + remove_head, 1 + *len);
1081 return(src);
1082 }
1083 return(NULL((void*)0));
1084}
1085
1086/**
1087 * xmlAddDefAttrs:
1088 * @ctxt: an XML parser context
1089 * @fullname: the element fullname
1090 * @fullattr: the attribute fullname
1091 * @value: the attribute value
1092 *
1093 * Add a defaulted attribute for an element
1094 */
1095static void
1096xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1097 const xmlChar *fullname,
1098 const xmlChar *fullattr,
1099 const xmlChar *value) {
1100 xmlDefAttrsPtr defaults;
1101 int len;
1102 const xmlChar *name;
1103 const xmlChar *prefix;
1104
1105 /*
1106 * Allows to detect attribute redefinitions
1107 */
1108 if (ctxt->attsSpecial != NULL((void*)0)) {
1109 if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL((void*)0))
1110 return;
1111 }
1112
1113 if (ctxt->attsDefault == NULL((void*)0)) {
1114 ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1115 if (ctxt->attsDefault == NULL((void*)0))
1116 goto mem_error;
1117 }
1118
1119 /*
1120 * split the element name into prefix:localname , the string found
1121 * are within the DTD and then not associated to namespace names.
1122 */
1123 name = xmlSplitQName3(fullname, &len);
1124 if (name == NULL((void*)0)) {
1125 name = xmlDictLookup(ctxt->dict, fullname, -1);
1126 prefix = NULL((void*)0);
1127 } else {
1128 name = xmlDictLookup(ctxt->dict, name, -1);
1129 prefix = xmlDictLookup(ctxt->dict, fullname, len);
1130 }
1131
1132 /*
1133 * make sure there is some storage
1134 */
1135 defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1136 if (defaults == NULL((void*)0)) {
1137 defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1138 (4 * 5) * sizeof(const xmlChar *));
1139 if (defaults == NULL((void*)0))
1140 goto mem_error;
1141 defaults->nbAttrs = 0;
1142 defaults->maxAttrs = 4;
1143 if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1144 defaults, NULL((void*)0)) < 0) {
1145 xmlFree(defaults);
1146 goto mem_error;
1147 }
1148 } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1149 xmlDefAttrsPtr temp;
1150
1151 temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1152 (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1153 if (temp == NULL((void*)0))
1154 goto mem_error;
1155 defaults = temp;
1156 defaults->maxAttrs *= 2;
1157 if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1158 defaults, NULL((void*)0)) < 0) {
1159 xmlFree(defaults);
1160 goto mem_error;
1161 }
1162 }
1163
1164 /*
1165 * Split the element name into prefix:localname , the string found
1166 * are within the DTD and hen not associated to namespace names.
1167 */
1168 name = xmlSplitQName3(fullattr, &len);
1169 if (name == NULL((void*)0)) {
1170 name = xmlDictLookup(ctxt->dict, fullattr, -1);
1171 prefix = NULL((void*)0);
1172 } else {
1173 name = xmlDictLookup(ctxt->dict, name, -1);
1174 prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1175 }
1176
1177 defaults->values[5 * defaults->nbAttrs] = name;
1178 defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1179 /* intern the string and precompute the end */
1180 len = xmlStrlen(value);
1181 value = xmlDictLookup(ctxt->dict, value, len);
1182 defaults->values[5 * defaults->nbAttrs + 2] = value;
1183 defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1184 if (ctxt->external)
1185 defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST(xmlChar *) "external";
1186 else
1187 defaults->values[5 * defaults->nbAttrs + 4] = NULL((void*)0);
1188 defaults->nbAttrs++;
1189
1190 return;
1191
1192mem_error:
1193 xmlErrMemory(ctxt, NULL((void*)0));
1194 return;
1195}
1196
1197/**
1198 * xmlAddSpecialAttr:
1199 * @ctxt: an XML parser context
1200 * @fullname: the element fullname
1201 * @fullattr: the attribute fullname
1202 * @type: the attribute type
1203 *
1204 * Register this attribute type
1205 */
1206static void
1207xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1208 const xmlChar *fullname,
1209 const xmlChar *fullattr,
1210 int type)
1211{
1212 if (ctxt->attsSpecial == NULL((void*)0)) {
1213 ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1214 if (ctxt->attsSpecial == NULL((void*)0))
1215 goto mem_error;
1216 }
1217
1218 if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL((void*)0))
1219 return;
1220
1221 xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1222 (void *) (long) type);
1223 return;
1224
1225mem_error:
1226 xmlErrMemory(ctxt, NULL((void*)0));
1227 return;
1228}
1229
1230/**
1231 * xmlCleanSpecialAttrCallback:
1232 *
1233 * Removes CDATA attributes from the special attribute table
1234 */
1235static void
1236xmlCleanSpecialAttrCallback(void *payload, void *data,
1237 const xmlChar *fullname, const xmlChar *fullattr,
1238 const xmlChar *unused ATTRIBUTE_UNUSED__attribute__((unused))) {
1239 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1240
1241 if (((long) payload) == XML_ATTRIBUTE_CDATA) {
1242 xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL((void*)0));
1243 }
1244}
1245
1246/**
1247 * xmlCleanSpecialAttr:
1248 * @ctxt: an XML parser context
1249 *
1250 * Trim the list of attributes defined to remove all those of type
1251 * CDATA as they are not special. This call should be done when finishing
1252 * to parse the DTD and before starting to parse the document root.
1253 */
1254static void
1255xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1256{
1257 if (ctxt->attsSpecial == NULL((void*)0))
1258 return;
1259
1260 xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1261
1262 if (xmlHashSize(ctxt->attsSpecial) == 0) {
1263 xmlHashFree(ctxt->attsSpecial, NULL((void*)0));
1264 ctxt->attsSpecial = NULL((void*)0);
1265 }
1266 return;
1267}
1268
1269/**
1270 * xmlCheckLanguageID:
1271 * @lang: pointer to the string value
1272 *
1273 * Checks that the value conforms to the LanguageID production:
1274 *
1275 * NOTE: this is somewhat deprecated, those productions were removed from
1276 * the XML Second edition.
1277 *
1278 * [33] LanguageID ::= Langcode ('-' Subcode)*
1279 * [34] Langcode ::= ISO639Code | IanaCode | UserCode
1280 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1281 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1282 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1283 * [38] Subcode ::= ([a-z] | [A-Z])+
1284 *
1285 * Returns 1 if correct 0 otherwise
1286 **/
1287int
1288xmlCheckLanguageID(const xmlChar * lang)
1289{
1290 const xmlChar *cur = lang;
1291
1292 if (cur == NULL((void*)0))
1293 return (0);
1294 if (((cur[0] == 'i') && (cur[1] == '-')) ||
1295 ((cur[0] == 'I') && (cur[1] == '-'))) {
1296 /*
1297 * IANA code
1298 */
1299 cur += 2;
1300 while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
1301 ((cur[0] >= 'a') && (cur[0] <= 'z')))
1302 cur++;
1303 } else if (((cur[0] == 'x') && (cur[1] == '-')) ||
1304 ((cur[0] == 'X') && (cur[1] == '-'))) {
1305 /*
1306 * User code
1307 */
1308 cur += 2;
1309 while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
1310 ((cur[0] >= 'a') && (cur[0] <= 'z')))
1311 cur++;
1312 } else if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1313 ((cur[0] >= 'a') && (cur[0] <= 'z'))) {
1314 /*
1315 * ISO639
1316 */
1317 cur++;
1318 if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1319 ((cur[0] >= 'a') && (cur[0] <= 'z')))
1320 cur++;
1321 else
1322 return (0);
1323 } else
1324 return (0);
1325 while (cur[0] != 0) { /* non input consuming */
1326 if (cur[0] != '-')
1327 return (0);
1328 cur++;
1329 if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1330 ((cur[0] >= 'a') && (cur[0] <= 'z')))
1331 cur++;
1332 else
1333 return (0);
1334 while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
1335 ((cur[0] >= 'a') && (cur[0] <= 'z')))
1336 cur++;
1337 }
1338 return (1);
1339}
1340
1341/************************************************************************
1342 * *
1343 * Parser stacks related functions and macros *
1344 * *
1345 ************************************************************************/
1346
1347static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1348 const xmlChar ** str);
1349
1350#ifdef SAX21
1351/**
1352 * nsPush:
1353 * @ctxt: an XML parser context
1354 * @prefix: the namespace prefix or NULL
1355 * @URL: the namespace name
1356 *
1357 * Pushes a new parser namespace on top of the ns stack
1358 *
1359 * Returns -1 in case of error, -2 if the namespace should be discarded
1360 * and the index in the stack otherwise.
1361 */
1362static int
1363nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1364{
1365 if (ctxt->options & XML_PARSE_NSCLEAN) {
1366 int i;
1367 for (i = 0;i < ctxt->nsNr;i += 2) {
1368 if (ctxt->nsTab[i] == prefix) {
1369 /* in scope */
1370 if (ctxt->nsTab[i + 1] == URL)
1371 return(-2);
1372 /* out of scope keep it */
1373 break;
1374 }
1375 }
1376 }
1377 if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL((void*)0))) {
1378 ctxt->nsMax = 10;
1379 ctxt->nsNr = 0;
1380 ctxt->nsTab = (const xmlChar **)
1381 xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1382 if (ctxt->nsTab == NULL((void*)0)) {
1383 xmlErrMemory(ctxt, NULL((void*)0));
1384 ctxt->nsMax = 0;
1385 return (-1);
1386 }
1387 } else if (ctxt->nsNr >= ctxt->nsMax) {
1388 const xmlChar ** tmp;
1389 ctxt->nsMax *= 2;
1390 tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1391 ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1392 if (tmp == NULL((void*)0)) {
1393 xmlErrMemory(ctxt, NULL((void*)0));
1394 ctxt->nsMax /= 2;
1395 return (-1);
1396 }
1397 ctxt->nsTab = tmp;
1398 }
1399 ctxt->nsTab[ctxt->nsNr++] = prefix;
1400 ctxt->nsTab[ctxt->nsNr++] = URL;
1401 return (ctxt->nsNr);
1402}
1403/**
1404 * nsPop:
1405 * @ctxt: an XML parser context
1406 * @nr: the number to pop
1407 *
1408 * Pops the top @nr parser prefix/namespace from the ns stack
1409 *
1410 * Returns the number of namespaces removed
1411 */
1412static int
1413nsPop(xmlParserCtxtPtr ctxt, int nr)
1414{
1415 int i;
1416
1417 if (ctxt->nsTab == NULL((void*)0)) return(0);
1418 if (ctxt->nsNr < nr) {
1419 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())), "Pbm popping %d NS\n", nr);
1420 nr = ctxt->nsNr;
1421 }
1422 if (ctxt->nsNr <= 0)
1423 return (0);
1424
1425 for (i = 0;i < nr;i++) {
1426 ctxt->nsNr--;
1427 ctxt->nsTab[ctxt->nsNr] = NULL((void*)0);
1428 }
1429 return(nr);
1430}
1431#endif
1432
1433static int
1434xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1435 const xmlChar **atts;
1436 int *attallocs;
1437 int maxatts;
1438
1439 if (ctxt->atts == NULL((void*)0)) {
1440 maxatts = 55; /* allow for 10 attrs by default */
1441 atts = (const xmlChar **)
1442 xmlMalloc(maxatts * sizeof(xmlChar *));
1443 if (atts == NULL((void*)0)) goto mem_error;
1444 ctxt->atts = atts;
1445 attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1446 if (attallocs == NULL((void*)0)) goto mem_error;
1447 ctxt->attallocs = attallocs;
1448 ctxt->maxatts = maxatts;
1449 } else if (nr + 5 > ctxt->maxatts) {
1450 maxatts = (nr + 5) * 2;
1451 atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1452 maxatts * sizeof(const xmlChar *));
1453 if (atts == NULL((void*)0)) goto mem_error;
1454 ctxt->atts = atts;
1455 attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1456 (maxatts / 5) * sizeof(int));
1457 if (attallocs == NULL((void*)0)) goto mem_error;
1458 ctxt->attallocs = attallocs;
1459 ctxt->maxatts = maxatts;
1460 }
1461 return(ctxt->maxatts);
1462mem_error:
1463 xmlErrMemory(ctxt, NULL((void*)0));
1464 return(-1);
1465}
1466
1467/**
1468 * inputPush:
1469 * @ctxt: an XML parser context
1470 * @value: the parser input
1471 *
1472 * Pushes a new parser input on top of the input stack
1473 *
1474 * Returns -1 in case of error, the index in the stack otherwise
1475 */
1476int
1477inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1478{
1479 if ((ctxt == NULL((void*)0)) || (value == NULL((void*)0)))
1480 return(-1);
1481 if (ctxt->inputNr >= ctxt->inputMax) {
1482 ctxt->inputMax *= 2;
1483 ctxt->inputTab =
1484 (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1485 ctxt->inputMax *
1486 sizeof(ctxt->inputTab[0]));
1487 if (ctxt->inputTab == NULL((void*)0)) {
1488 xmlErrMemory(ctxt, NULL((void*)0));
1489 xmlFreeInputStream(value);
1490 ctxt->inputMax /= 2;
1491 value = NULL((void*)0);
1492 return (-1);
1493 }
1494 }
1495 ctxt->inputTab[ctxt->inputNr] = value;
1496 ctxt->input = value;
1497 return (ctxt->inputNr++);
1498}
1499/**
1500 * inputPop:
1501 * @ctxt: an XML parser context
1502 *
1503 * Pops the top parser input from the input stack
1504 *
1505 * Returns the input just removed
1506 */
1507xmlParserInputPtr
1508inputPop(xmlParserCtxtPtr ctxt)
1509{
1510 xmlParserInputPtr ret;
1511
1512 if (ctxt == NULL((void*)0))
1513 return(NULL((void*)0));
1514 if (ctxt->inputNr <= 0)
1515 return (NULL((void*)0));
1516 ctxt->inputNr--;
1517 if (ctxt->inputNr > 0)
1518 ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1519 else
1520 ctxt->input = NULL((void*)0);
1521 ret = ctxt->inputTab[ctxt->inputNr];
1522 ctxt->inputTab[ctxt->inputNr] = NULL((void*)0);
1523 return (ret);
1524}
1525/**
1526 * nodePush:
1527 * @ctxt: an XML parser context
1528 * @value: the element node
1529 *
1530 * Pushes a new element node on top of the node stack
1531 *
1532 * Returns -1 in case of error, the index in the stack otherwise
1533 */
1534int
1535nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1536{
1537 if (ctxt == NULL((void*)0)) return(0);
1538 if (ctxt->nodeNr >= ctxt->nodeMax) {
1539 xmlNodePtr *tmp;
1540
1541 tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1542 ctxt->nodeMax * 2 *
1543 sizeof(ctxt->nodeTab[0]));
1544 if (tmp == NULL((void*)0)) {
1545 xmlErrMemory(ctxt, NULL((void*)0));
1546 return (-1);
1547 }
1548 ctxt->nodeTab = tmp;
1549 ctxt->nodeMax *= 2;
1550 }
1551 if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1552 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1553 xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1554 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1555 xmlParserMaxDepth);
1556 ctxt->instate = XML_PARSER_EOF;
1557 return(-1);
1558 }
1559 ctxt->nodeTab[ctxt->nodeNr] = value;
1560 ctxt->node = value;
1561 return (ctxt->nodeNr++);
1562}
1563
1564/**
1565 * nodePop:
1566 * @ctxt: an XML parser context
1567 *
1568 * Pops the top element node from the node stack
1569 *
1570 * Returns the node just removed
1571 */
1572xmlNodePtr
1573nodePop(xmlParserCtxtPtr ctxt)
1574{
1575 xmlNodePtr ret;
1576
1577 if (ctxt == NULL((void*)0)) return(NULL((void*)0));
1578 if (ctxt->nodeNr <= 0)
1579 return (NULL((void*)0));
1580 ctxt->nodeNr--;
1581 if (ctxt->nodeNr > 0)
1582 ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1583 else
1584 ctxt->node = NULL((void*)0);
1585 ret = ctxt->nodeTab[ctxt->nodeNr];
1586 ctxt->nodeTab[ctxt->nodeNr] = NULL((void*)0);
1587 return (ret);
1588}
1589
1590#ifdef LIBXML_PUSH_ENABLED
1591/**
1592 * nameNsPush:
1593 * @ctxt: an XML parser context
1594 * @value: the element name
1595 * @prefix: the element prefix
1596 * @URI: the element namespace name
1597 *
1598 * Pushes a new element name/prefix/URL on top of the name stack
1599 *
1600 * Returns -1 in case of error, the index in the stack otherwise
1601 */
1602static int
1603nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1604 const xmlChar *prefix, const xmlChar *URI, int nsNr)
1605{
1606 if (ctxt->nameNr >= ctxt->nameMax) {
1607 const xmlChar * *tmp;
1608 void **tmp2;
1609 ctxt->nameMax *= 2;
1610 tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1611 ctxt->nameMax *
1612 sizeof(ctxt->nameTab[0]));
1613 if (tmp == NULL((void*)0)) {
1614 ctxt->nameMax /= 2;
1615 goto mem_error;
1616 }
1617 ctxt->nameTab = tmp;
1618 tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
1619 ctxt->nameMax * 3 *
1620 sizeof(ctxt->pushTab[0]));
1621 if (tmp2 == NULL((void*)0)) {
1622 ctxt->nameMax /= 2;
1623 goto mem_error;
1624 }
1625 ctxt->pushTab = tmp2;
1626 }
1627 ctxt->nameTab[ctxt->nameNr] = value;
1628 ctxt->name = value;
1629 ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
1630 ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
1631 ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
1632 return (ctxt->nameNr++);
1633mem_error:
1634 xmlErrMemory(ctxt, NULL((void*)0));
1635 return (-1);
1636}
1637/**
1638 * nameNsPop:
1639 * @ctxt: an XML parser context
1640 *
1641 * Pops the top element/prefix/URI name from the name stack
1642 *
1643 * Returns the name just removed
1644 */
1645static const xmlChar *
1646nameNsPop(xmlParserCtxtPtr ctxt)
1647{
1648 const xmlChar *ret;
1649
1650 if (ctxt->nameNr <= 0)
1651 return (NULL((void*)0));
1652 ctxt->nameNr--;
1653 if (ctxt->nameNr > 0)
1654 ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1655 else
1656 ctxt->name = NULL((void*)0);
1657 ret = ctxt->nameTab[ctxt->nameNr];
1658 ctxt->nameTab[ctxt->nameNr] = NULL((void*)0);
1659 return (ret);
1660}
1661#endif /* LIBXML_PUSH_ENABLED */
1662
1663/**
1664 * namePush:
1665 * @ctxt: an XML parser context
1666 * @value: the element name
1667 *
1668 * Pushes a new element name on top of the name stack
1669 *
1670 * Returns -1 in case of error, the index in the stack otherwise
1671 */
1672int
1673namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1674{
1675 if (ctxt == NULL((void*)0)) return (-1);
1676
1677 if (ctxt->nameNr >= ctxt->nameMax) {
1678 const xmlChar * *tmp;
1679 ctxt->nameMax *= 2;
1680 tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1681 ctxt->nameMax *
1682 sizeof(ctxt->nameTab[0]));
1683 if (tmp == NULL((void*)0)) {
1684 ctxt->nameMax /= 2;
1685 goto mem_error;
1686 }
1687 ctxt->nameTab = tmp;
1688 }
1689 ctxt->nameTab[ctxt->nameNr] = value;
1690 ctxt->name = value;
1691 return (ctxt->nameNr++);
1692mem_error:
1693 xmlErrMemory(ctxt, NULL((void*)0));
1694 return (-1);
1695}
1696/**
1697 * namePop:
1698 * @ctxt: an XML parser context
1699 *
1700 * Pops the top element name from the name stack
1701 *
1702 * Returns the name just removed
1703 */
1704const xmlChar *
1705namePop(xmlParserCtxtPtr ctxt)
1706{
1707 const xmlChar *ret;
1708
1709 if ((ctxt == NULL((void*)0)) || (ctxt->nameNr <= 0))
1710 return (NULL((void*)0));
1711 ctxt->nameNr--;
1712 if (ctxt->nameNr > 0)
1713 ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1714 else
1715 ctxt->name = NULL((void*)0);
1716 ret = ctxt->nameTab[ctxt->nameNr];
1717 ctxt->nameTab[ctxt->nameNr] = NULL((void*)0);
1718 return (ret);
1719}
1720
1721static int spacePush(xmlParserCtxtPtr ctxt, int val) {
1722 if (ctxt->spaceNr >= ctxt->spaceMax) {
1723 int *tmp;
1724
1725 ctxt->spaceMax *= 2;
1726 tmp = (int *) xmlRealloc(ctxt->spaceTab,
1727 ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
1728 if (tmp == NULL((void*)0)) {
1729 xmlErrMemory(ctxt, NULL((void*)0));
1730 ctxt->spaceMax /=2;
1731 return(-1);
1732 }
1733 ctxt->spaceTab = tmp;
1734 }
1735 ctxt->spaceTab[ctxt->spaceNr] = val;
1736 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
1737 return(ctxt->spaceNr++);
1738}
1739
1740static int spacePop(xmlParserCtxtPtr ctxt) {
1741 int ret;
1742 if (ctxt->spaceNr <= 0) return(0);
1743 ctxt->spaceNr--;
1744 if (ctxt->spaceNr > 0)
1745 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
1746 else
1747 ctxt->space = &ctxt->spaceTab[0];
1748 ret = ctxt->spaceTab[ctxt->spaceNr];
1749 ctxt->spaceTab[ctxt->spaceNr] = -1;
1750 return(ret);
1751}
1752
1753/*
1754 * Macros for accessing the content. Those should be used only by the parser,
1755 * and not exported.
1756 *
1757 * Dirty macros, i.e. one often need to make assumption on the context to
1758 * use them
1759 *
1760 * CUR_PTR return the current pointer to the xmlChar to be parsed.
1761 * To be used with extreme caution since operations consuming
1762 * characters may move the input buffer to a different location !
1763 * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled
1764 * This should be used internally by the parser
1765 * only to compare to ASCII values otherwise it would break when
1766 * running with UTF-8 encoding.
1767 * RAW same as CUR but in the input buffer, bypass any token
1768 * extraction that may have been done
1769 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
1770 * to compare on ASCII based substring.
1771 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1772 * strings without newlines within the parser.
1773 * NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
1774 * defined char within the parser.
1775 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1776 *
1777 * NEXT Skip to the next character, this does the proper decoding
1778 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
1779 * NEXTL(l) Skip the current unicode character of l xmlChars long.
1780 * CUR_CHAR(l) returns the current unicode character (int), set l
1781 * to the number of xmlChars used for the encoding [0-5].
1782 * CUR_SCHAR same but operate on a string instead of the context
1783 * COPY_BUF copy the current unicode char to the target buffer, increment
1784 * the index
1785 * GROW, SHRINK handling of input buffers
1786 */
1787
1788#define RAW(*ctxt->input->cur) (*ctxt->input->cur)
1789#define CUR(*ctxt->input->cur) (*ctxt->input->cur)
1790#define NXT(val)ctxt->input->cur[(val)] ctxt->input->cur[(val)]
1791#define CUR_PTRctxt->input->cur ctxt->input->cur
1792
1793#define CMP4( s, c1, c2, c3, c4 )( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 )
\
1794 ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
1795 ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
1796#define CMP5( s, c1, c2, c3, c4, c5 )( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 ) && ((unsigned
char *) s)[ 4 ] == c5 )
\
1797 ( CMP4( s, c1, c2, c3, c4 )( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 )
&& ((unsigned char *) s)[ 4 ] == c5 )
1798#define CMP6( s, c1, c2, c3, c4, c5, c6 )( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 ) && ((unsigned
char *) s)[ 4 ] == c5 ) && ((unsigned char *) s)[ 5 ]
== c6 )
\
1799 ( CMP5( s, c1, c2, c3, c4, c5 )( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 ) && ((unsigned
char *) s)[ 4 ] == c5 )
&& ((unsigned char *) s)[ 5 ] == c6 )
1800#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 )( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
)
\
1801 ( CMP6( s, c1, c2, c3, c4, c5, c6 )( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char
*) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] == c3
&& ((unsigned char *) s)[ 3 ] == c4 ) && ((unsigned
char *) s)[ 4 ] == c5 ) && ((unsigned char *) s)[ 5 ]
== c6 )
&& ((unsigned char *) s)[ 6 ] == c7 )
1802#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 )( ( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
) && ((unsigned char *) s)[ 7 ] == c8 )
\
1803 ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 )( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
)
&& ((unsigned char *) s)[ 7 ] == c8 )
1804#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 )( ( ( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
) && ((unsigned char *) s)[ 7 ] == c8 ) && (
(unsigned char *) s)[ 8 ] == c9 )
\
1805 ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 )( ( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
) && ((unsigned char *) s)[ 7 ] == c8 )
&& \
1806 ((unsigned char *) s)[ 8 ] == c9 )
1807#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 )( ( ( ( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
) && ((unsigned char *) s)[ 7 ] == c8 ) && (
(unsigned char *) s)[ 8 ] == c9 ) && ((unsigned char *
) s)[ 9 ] == c10 )
\
1808 ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 )( ( ( ( ( ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned
char *) s)[ 1 ] == c2 && ((unsigned char *) s)[ 2 ] ==
c3 && ((unsigned char *) s)[ 3 ] == c4 ) && (
(unsigned char *) s)[ 4 ] == c5 ) && ((unsigned char *
) s)[ 5 ] == c6 ) && ((unsigned char *) s)[ 6 ] == c7
) && ((unsigned char *) s)[ 7 ] == c8 ) && (
(unsigned char *) s)[ 8 ] == c9 )
&& \
1809 ((unsigned char *) s)[ 9 ] == c10 )
1810
1811#define SKIP(val)do { ctxt->nbChars += (val),ctxt->input->cur += (val
),ctxt->input->col+=(val); if (*ctxt->input->cur ==
'%') xmlParserHandlePEReference(ctxt); if ((*ctxt->input->
cur == 0) && (xmlParserInputGrow(ctxt->input, 250)
<= 0)) xmlPopInput(ctxt); } while (0)
do { \
1812 ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val); \
1813 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
1814 if ((*ctxt->input->cur == 0) && \
1815 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK250) <= 0)) \
1816 xmlPopInput(ctxt); \
1817 } while (0)
1818
1819#define SKIPL(val)do { int skipl; for(skipl=0; skipl<val; skipl++) { if (*(ctxt
->input->cur) == '\n') { ctxt->input->line++; ctxt
->input->col = 1; } else ctxt->input->col++; ctxt
->nbChars++; ctxt->input->cur++; } if (*ctxt->input
->cur == '%') xmlParserHandlePEReference(ctxt); if ((*ctxt
->input->cur == 0) && (xmlParserInputGrow(ctxt->
input, 250) <= 0)) xmlPopInput(ctxt); } while (0)
do { \
1820 int skipl; \
1821 for(skipl=0; skipl<val; skipl++) { \
1822 if (*(ctxt->input->cur) == '\n') { \
1823 ctxt->input->line++; ctxt->input->col = 1; \
1824 } else ctxt->input->col++; \
1825 ctxt->nbChars++; \
1826 ctxt->input->cur++; \
1827 } \
1828 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
1829 if ((*ctxt->input->cur == 0) && \
1830 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK250) <= 0)) \
1831 xmlPopInput(ctxt); \
1832 } while (0)
1833
1834#define SHRINKif ((ctxt->progressive == 0) && (ctxt->input->
cur - ctxt->input->base > 2 * 250) && (ctxt->
input->end - ctxt->input->cur < 2 * 250)) xmlSHRINK
(ctxt);
if ((ctxt->progressive == 0) && \
1835 (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK250) && \
1836 (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK250)) \
1837 xmlSHRINK (ctxt);
1838
1839static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
1840 xmlParserInputShrink(ctxt->input);
1841 if ((*ctxt->input->cur == 0) &&
1842 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK250) <= 0))
1843 xmlPopInput(ctxt);
1844 }
1845
1846#define GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
if ((ctxt->progressive == 0) && \
1847 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK250)) \
1848 xmlGROW (ctxt);
1849
1850static void xmlGROW (xmlParserCtxtPtr ctxt) {
1851 xmlParserInputGrow(ctxt->input, INPUT_CHUNK250);
1852 if ((*ctxt->input->cur == 0) &&
1853 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK250) <= 0))
1854 xmlPopInput(ctxt);
1855}
1856
1857#define SKIP_BLANKSxmlSkipBlankChars(ctxt) xmlSkipBlankChars(ctxt)
1858
1859#define NEXTxmlNextChar(ctxt) xmlNextChar(ctxt)
1860
1861#define NEXT1{ ctxt->input->col++; ctxt->input->cur++; ctxt->
nbChars++; if (*ctxt->input->cur == 0) xmlParserInputGrow
(ctxt->input, 250); }
{ \
1862 ctxt->input->col++; \
1863 ctxt->input->cur++; \
1864 ctxt->nbChars++; \
1865 if (*ctxt->input->cur == 0) \
1866 xmlParserInputGrow(ctxt->input, INPUT_CHUNK250); \
1867 }
1868
1869#define NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
do { \
1870 if (*(ctxt->input->cur) == '\n') { \
1871 ctxt->input->line++; ctxt->input->col = 1; \
1872 } else ctxt->input->col++; \
1873 ctxt->input->cur += l; \
1874 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
1875 } while (0)
1876
1877#define CUR_CHAR(l)xmlCurrentChar(ctxt, &l) xmlCurrentChar(ctxt, &l)
1878#define CUR_SCHAR(s, l)xmlStringCurrentChar(ctxt, s, &l) xmlStringCurrentChar(ctxt, s, &l)
1879
1880#define COPY_BUF(l,b,i,v)if (l == 1) b[i++] = (xmlChar) v; else i += xmlCopyCharMultiByte
(&b[i],v)
\
1881 if (l == 1) b[i++] = (xmlChar) v; \
1882 else i += xmlCopyCharMultiByte(&b[i],v)
1883
1884/**
1885 * xmlSkipBlankChars:
1886 * @ctxt: the XML parser context
1887 *
1888 * skip all blanks character found at that point in the input streams.
1889 * It pops up finished entities in the process if allowable at that point.
1890 *
1891 * Returns the number of space chars skipped
1892 */
1893
1894int
1895xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
1896 int res = 0;
1897
1898 /*
1899 * It's Okay to use CUR/NEXT here since all the blanks are on
1900 * the ASCII range.
1901 */
1902 if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
1903 const xmlChar *cur;
1904 /*
1905 * if we are in the document content, go really fast
1906 */
1907 cur = ctxt->input->cur;
1908 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) {
1909 if (*cur == '\n') {
1910 ctxt->input->line++; ctxt->input->col = 1;
1911 }
1912 cur++;
1913 res++;
1914 if (*cur == 0) {
1915 ctxt->input->cur = cur;
1916 xmlParserInputGrow(ctxt->input, INPUT_CHUNK250);
1917 cur = ctxt->input->cur;
1918 }
1919 }
1920 ctxt->input->cur = cur;
1921 } else {
1922 int cur;
1923 do {
1924 cur = CUR(*ctxt->input->cur);
1925 while (IS_BLANK_CH(cur)(((cur) == 0x20) || ((0x9 <= (cur)) && ((cur) <=
0xa)) || ((cur) == 0xd))
) { /* CHECKED tstblanks.xml */
1926 NEXTxmlNextChar(ctxt);
1927 cur = CUR(*ctxt->input->cur);
1928 res++;
1929 }
1930 while ((cur == 0) && (ctxt->inputNr > 1) &&
1931 (ctxt->instate != XML_PARSER_COMMENT)) {
1932 xmlPopInput(ctxt);
1933 cur = CUR(*ctxt->input->cur);
1934 }
1935 /*
1936 * Need to handle support of entities branching here
1937 */
1938 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
1939 } while (IS_BLANK(cur)(((cur) < 0x100) ? ((((cur)) == 0x20) || ((0x9 <= ((cur
))) && (((cur)) <= 0xa)) || (((cur)) == 0xd)) : 0)
); /* CHECKED tstblanks.xml */
1940 }
1941 return(res);
1942}
1943
1944/************************************************************************
1945 * *
1946 * Commodity functions to handle entities *
1947 * *
1948 ************************************************************************/
1949
1950/**
1951 * xmlPopInput:
1952 * @ctxt: an XML parser context
1953 *
1954 * xmlPopInput: the current input pointed by ctxt->input came to an end
1955 * pop it and return the next char.
1956 *
1957 * Returns the current xmlChar in the parser context
1958 */
1959xmlChar
1960xmlPopInput(xmlParserCtxtPtr ctxt) {
1961 if ((ctxt == NULL((void*)0)) || (ctxt->inputNr <= 1)) return(0);
1962 if (xmlParserDebugEntities(*(__xmlParserDebugEntities())))
1963 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1964 "Popping input %d\n", ctxt->inputNr);
1965 xmlFreeInputStream(inputPop(ctxt));
1966 if ((*ctxt->input->cur == 0) &&
1967 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK250) <= 0))
1968 return(xmlPopInput(ctxt));
1969 return(CUR(*ctxt->input->cur));
1970}
1971
1972/**
1973 * xmlPushInput:
1974 * @ctxt: an XML parser context
1975 * @input: an XML parser input fragment (entity, XML fragment ...).
1976 *
1977 * xmlPushInput: switch to a new input stream which is stacked on top
1978 * of the previous one(s).
1979 * Returns -1 in case of error or the index in the input stack
1980 */
1981int
1982xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
1983 int ret;
1984 if (input == NULL((void*)0)) return(-1);
1985
1986 if (xmlParserDebugEntities(*(__xmlParserDebugEntities()))) {
1987 if ((ctxt->input != NULL((void*)0)) && (ctxt->input->filename))
1988 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1989 "%s(%d): ", ctxt->input->filename,
1990 ctxt->input->line);
1991 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1992 "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
1993 }
1994 ret = inputPush(ctxt, input);
1995 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
1996 return(ret);
1997}
1998
1999/**
2000 * xmlParseCharRef:
2001 * @ctxt: an XML parser context
2002 *
2003 * parse Reference declarations
2004 *
2005 * [66] CharRef ::= '&#' [0-9]+ ';' |
2006 * '&#x' [0-9a-fA-F]+ ';'
2007 *
2008 * [ WFC: Legal Character ]
2009 * Characters referred to using character references must match the
2010 * production for Char.
2011 *
2012 * Returns the value parsed (as an int), 0 in case of error
2013 */
2014int
2015xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2016 unsigned int val = 0;
2017 int count = 0;
2018 unsigned int outofrange = 0;
2019
2020 /*
2021 * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2022 */
2023 if ((RAW(*ctxt->input->cur) == '&') && (NXT(1)ctxt->input->cur[(1)] == '#') &&
2024 (NXT(2)ctxt->input->cur[(2)] == 'x')) {
2025 SKIP(3)do { ctxt->nbChars += (3),ctxt->input->cur += (3),ctxt
->input->col+=(3); if (*ctxt->input->cur == '%') xmlParserHandlePEReference
(ctxt); if ((*ctxt->input->cur == 0) && (xmlParserInputGrow
(ctxt->input, 250) <= 0)) xmlPopInput(ctxt); } while (0
)
;
2026 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
2027 while (RAW(*ctxt->input->cur) != ';') { /* loop blocked by count */
2028 if (count++ > 20) {
2029 count = 0;
2030 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
2031 }
2032 if ((RAW(*ctxt->input->cur) >= '0') && (RAW(*ctxt->input->cur) <= '9'))
2033 val = val * 16 + (CUR(*ctxt->input->cur) - '0');
2034 else if ((RAW(*ctxt->input->cur) >= 'a') && (RAW(*ctxt->input->cur) <= 'f') && (count < 20))
2035 val = val * 16 + (CUR(*ctxt->input->cur) - 'a') + 10;
2036 else if ((RAW(*ctxt->input->cur) >= 'A') && (RAW(*ctxt->input->cur) <= 'F') && (count < 20))
2037 val = val * 16 + (CUR(*ctxt->input->cur) - 'A') + 10;
2038 else {
2039 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL((void*)0));
2040 val = 0;
2041 break;
2042 }
2043 if (val > 0x10FFFF)
2044 outofrange = val;
2045
2046 NEXTxmlNextChar(ctxt);
2047 count++;
2048 }
2049 if (RAW(*ctxt->input->cur) == ';') {
2050 /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2051 ctxt->input->col++;
2052 ctxt->nbChars ++;
2053 ctxt->input->cur++;
2054 }
2055 } else if ((RAW(*ctxt->input->cur) == '&') && (NXT(1)ctxt->input->cur[(1)] == '#')) {
2056 SKIP(2)do { ctxt->nbChars += (2),ctxt->input->cur += (2),ctxt
->input->col+=(2); if (*ctxt->input->cur == '%') xmlParserHandlePEReference
(ctxt); if ((*ctxt->input->cur == 0) && (xmlParserInputGrow
(ctxt->input, 250) <= 0)) xmlPopInput(ctxt); } while (0
)
;
2057 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
2058 while (RAW(*ctxt->input->cur) != ';') { /* loop blocked by count */
2059 if (count++ > 20) {
2060 count = 0;
2061 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
2062 }
2063 if ((RAW(*ctxt->input->cur) >= '0') && (RAW(*ctxt->input->cur) <= '9'))
2064 val = val * 10 + (CUR(*ctxt->input->cur) - '0');
2065 else {
2066 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL((void*)0));
2067 val = 0;
2068 break;
2069 }
2070 if (val > 0x10FFFF)
2071 outofrange = val;
2072
2073 NEXTxmlNextChar(ctxt);
2074 count++;
2075 }
2076 if (RAW(*ctxt->input->cur) == ';') {
2077 /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2078 ctxt->input->col++;
2079 ctxt->nbChars ++;
2080 ctxt->input->cur++;
2081 }
2082 } else {
2083 xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL((void*)0));
2084 }
2085
2086 /*
2087 * [ WFC: Legal Character ]
2088 * Characters referred to using character references must match the
2089 * production for Char.
2090 */
2091 if ((IS_CHAR(val)(((val) < 0x100) ? (((0x9 <= ((val))) && (((val
)) <= 0xa)) || (((val)) == 0xd) || (0x20 <= ((val)))) :
(((0x100 <= (val)) && ((val) <= 0xd7ff)) || ((
0xe000 <= (val)) && ((val) <= 0xfffd)) || ((0x10000
<= (val)) && ((val) <= 0x10ffff))))
&& (outofrange == 0))) {
2092 return(val);
2093 } else {
2094 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2095 "xmlParseCharRef: invalid xmlChar value %d\n",
2096 val);
2097 }
2098 return(0);
2099}
2100
2101/**
2102 * xmlParseStringCharRef:
2103 * @ctxt: an XML parser context
2104 * @str: a pointer to an index in the string
2105 *
2106 * parse Reference declarations, variant parsing from a string rather
2107 * than an an input flow.
2108 *
2109 * [66] CharRef ::= '&#' [0-9]+ ';' |
2110 * '&#x' [0-9a-fA-F]+ ';'
2111 *
2112 * [ WFC: Legal Character ]
2113 * Characters referred to using character references must match the
2114 * production for Char.
2115 *
2116 * Returns the value parsed (as an int), 0 in case of error, str will be
2117 * updated to the current value of the index
2118 */
2119static int
2120xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2121 const xmlChar *ptr;
2122 xmlChar cur;
2123 unsigned int val = 0;
2124 unsigned int outofrange = 0;
2125
2126 if ((str == NULL((void*)0)) || (*str == NULL((void*)0))) return(0);
2127 ptr = *str;
2128 cur = *ptr;
2129 if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2130 ptr += 3;
2131 cur = *ptr;
2132 while (cur != ';') { /* Non input consuming loop */
2133 if ((cur >= '0') && (cur <= '9'))
2134 val = val * 16 + (cur - '0');
2135 else if ((cur >= 'a') && (cur <= 'f'))
2136 val = val * 16 + (cur - 'a') + 10;
2137 else if ((cur >= 'A') && (cur <= 'F'))
2138 val = val * 16 + (cur - 'A') + 10;
2139 else {
2140 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL((void*)0));
2141 val = 0;
2142 break;
2143 }
2144 if (val > 0x10FFFF)
2145 outofrange = val;
2146
2147 ptr++;
2148 cur = *ptr;
2149 }
2150 if (cur == ';')
2151 ptr++;
2152 } else if ((cur == '&') && (ptr[1] == '#')){
2153 ptr += 2;
2154 cur = *ptr;
2155 while (cur != ';') { /* Non input consuming loops */
2156 if ((cur >= '0') && (cur <= '9'))
2157 val = val * 10 + (cur - '0');
2158 else {
2159 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL((void*)0));
2160 val = 0;
2161 break;
2162 }
2163 if (val > 0x10FFFF)
2164 outofrange = val;
2165
2166 ptr++;
2167 cur = *ptr;
2168 }
2169 if (cur == ';')
2170 ptr++;
2171 } else {
2172 xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL((void*)0));
2173 return(0);
2174 }
2175 *str = ptr;
2176
2177 /*
2178 * [ WFC: Legal Character ]
2179 * Characters referred to using character references must match the
2180 * production for Char.
2181 */
2182 if ((IS_CHAR(val)(((val) < 0x100) ? (((0x9 <= ((val))) && (((val
)) <= 0xa)) || (((val)) == 0xd) || (0x20 <= ((val)))) :
(((0x100 <= (val)) && ((val) <= 0xd7ff)) || ((
0xe000 <= (val)) && ((val) <= 0xfffd)) || ((0x10000
<= (val)) && ((val) <= 0x10ffff))))
&& (outofrange == 0))) {
2183 return(val);
2184 } else {
2185 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2186 "xmlParseStringCharRef: invalid xmlChar value %d\n",
2187 val);
2188 }
2189 return(0);
2190}
2191
2192/**
2193 * xmlNewBlanksWrapperInputStream:
2194 * @ctxt: an XML parser context
2195 * @entity: an Entity pointer
2196 *
2197 * Create a new input stream for wrapping
2198 * blanks around a PEReference
2199 *
2200 * Returns the new input stream or NULL
2201 */
2202
2203static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
2204
2205static xmlParserInputPtr
2206xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
2207 xmlParserInputPtr input;
2208 xmlChar *buffer;
2209 size_t length;
2210 if (entity == NULL((void*)0)) {
2211 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2212 "xmlNewBlanksWrapperInputStream entity\n");
2213 return(NULL((void*)0));
2214 }
2215 if (xmlParserDebugEntities(*(__xmlParserDebugEntities())))
2216 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2217 "new blanks wrapper for entity: %s\n", entity->name);
2218 input = xmlNewInputStream(ctxt);
2219 if (input == NULL((void*)0)) {
2220 return(NULL((void*)0));
2221 }
2222 length = xmlStrlen(entity->name) + 5;
2223 buffer = xmlMallocAtomic(length);
2224 if (buffer == NULL((void*)0)) {
2225 xmlErrMemory(ctxt, NULL((void*)0));
2226 xmlFree(input);
2227 return(NULL((void*)0));
2228 }
2229 buffer [0] = ' ';
2230 buffer [1] = '%';
2231 buffer [length-3] = ';';
2232 buffer [length-2] = ' ';
2233 buffer [length-1] = 0;
2234 memcpy(buffer + 2, entity->name, length - 5);
2235 input->free = deallocblankswrapper;
2236 input->base = buffer;
2237 input->cur = buffer;
2238 input->length = length;
2239 input->end = &buffer[length];
2240 return(input);
2241}
2242
2243/**
2244 * xmlParserHandlePEReference:
2245 * @ctxt: the parser context
2246 *
2247 * [69] PEReference ::= '%' Name ';'
2248 *
2249 * [ WFC: No Recursion ]
2250 * A parsed entity must not contain a recursive
2251 * reference to itself, either directly or indirectly.
2252 *
2253 * [ WFC: Entity Declared ]
2254 * In a document without any DTD, a document with only an internal DTD
2255 * subset which contains no parameter entity references, or a document
2256 * with "standalone='yes'", ... ... The declaration of a parameter
2257 * entity must precede any reference to it...
2258 *
2259 * [ VC: Entity Declared ]
2260 * In a document with an external subset or external parameter entities
2261 * with "standalone='no'", ... ... The declaration of a parameter entity
2262 * must precede any reference to it...
2263 *
2264 * [ WFC: In DTD ]
2265 * Parameter-entity references may only appear in the DTD.
2266 * NOTE: misleading but this is handled.
2267 *
2268 * A PEReference may have been detected in the current input stream
2269 * the handling is done accordingly to
2270 * http://www.w3.org/TR/REC-xml#entproc
2271 * i.e.
2272 * - Included in literal in entity values
2273 * - Included as Parameter Entity reference within DTDs
2274 */
2275void
2276xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2277 const xmlChar *name;
2278 xmlEntityPtr entity = NULL((void*)0);
2279 xmlParserInputPtr input;
2280
2281 if (RAW(*ctxt->input->cur) != '%') return;
2282 switch(ctxt->instate) {
2283 case XML_PARSER_CDATA_SECTION:
2284 return;
2285 case XML_PARSER_COMMENT:
2286 return;
2287 case XML_PARSER_START_TAG:
2288 return;
2289 case XML_PARSER_END_TAG:
2290 return;
2291 case XML_PARSER_EOF:
2292 xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL((void*)0));
2293 return;
2294 case XML_PARSER_PROLOG:
2295 case XML_PARSER_START:
2296 case XML_PARSER_MISC:
2297 xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL((void*)0));
2298 return;
2299 case XML_PARSER_ENTITY_DECL:
2300 case XML_PARSER_CONTENT:
2301 case XML_PARSER_ATTRIBUTE_VALUE:
2302 case XML_PARSER_PI:
2303 case XML_PARSER_SYSTEM_LITERAL:
2304 case XML_PARSER_PUBLIC_LITERAL:
2305 /* we just ignore it there */
2306 return;
2307 case XML_PARSER_EPILOG:
2308 xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL((void*)0));
2309 return;
2310 case XML_PARSER_ENTITY_VALUE:
2311 /*
2312 * NOTE: in the case of entity values, we don't do the
2313 * substitution here since we need the literal
2314 * entity value to be able to save the internal
2315 * subset of the document.
2316 * This will be handled by xmlStringDecodeEntities
2317 */
2318 return;
2319 case XML_PARSER_DTD:
2320 /*
2321 * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2322 * In the internal DTD subset, parameter-entity references
2323 * can occur only where markup declarations can occur, not
2324 * within markup declarations.
2325 * In that case this is handled in xmlParseMarkupDecl
2326 */
2327 if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2328 return;
2329 if (IS_BLANK_CH(NXT(1))(((ctxt->input->cur[(1)]) == 0x20) || ((0x9 <= (ctxt
->input->cur[(1)])) && ((ctxt->input->cur
[(1)]) <= 0xa)) || ((ctxt->input->cur[(1)]) == 0xd))
|| NXT(1)ctxt->input->cur[(1)] == 0)
2330 return;
2331 break;
2332 case XML_PARSER_IGNORE:
2333 return;
2334 }
2335
2336 NEXTxmlNextChar(ctxt);
2337 name = xmlParseName(ctxt);
2338 if (xmlParserDebugEntities(*(__xmlParserDebugEntities())))
2339 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2340 "PEReference: %s\n", name);
2341 if (name == NULL((void*)0)) {
2342 xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL((void*)0));
2343 } else {
2344 if (RAW(*ctxt->input->cur) == ';') {
2345 NEXTxmlNextChar(ctxt);
2346 if ((ctxt->sax != NULL((void*)0)) && (ctxt->sax->getParameterEntity != NULL((void*)0)))
2347 entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
2348 if (entity == NULL((void*)0)) {
2349
2350 /*
2351 * [ WFC: Entity Declared ]
2352 * In a document without any DTD, a document with only an
2353 * internal DTD subset which contains no parameter entity
2354 * references, or a document with "standalone='yes'", ...
2355 * ... The declaration of a parameter entity must precede
2356 * any reference to it...
2357 */
2358 if ((ctxt->standalone == 1) ||
2359 ((ctxt->hasExternalSubset == 0) &&
2360 (ctxt->hasPErefs == 0))) {
2361 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
2362 "PEReference: %%%s; not found\n", name);
2363 } else {
2364 /*
2365 * [ VC: Entity Declared ]
2366 * In a document with an external subset or external
2367 * parameter entities with "standalone='no'", ...
2368 * ... The declaration of a parameter entity must precede
2369 * any reference to it...
2370 */
2371 if ((ctxt->validate) && (ctxt->vctxt.error != NULL((void*)0))) {
2372 xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
2373 "PEReference: %%%s; not found\n",
2374 name, NULL((void*)0));
2375 } else
2376 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
2377 "PEReference: %%%s; not found\n",
2378 name, NULL((void*)0));
2379 ctxt->valid = 0;
2380 }
2381 } else if (ctxt->input->free != deallocblankswrapper) {
2382 input = xmlNewBlanksWrapperInputStream(ctxt, entity);
2383 if (xmlPushInput(ctxt, input) < 0)
2384 return;
2385 } else {
2386 if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
2387 (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
2388 xmlChar start[4];
2389 xmlCharEncoding enc;
2390
2391 /*
2392 * handle the extra spaces added before and after
2393 * c.f. http://www.w3.org/TR/REC-xml#as-PE
2394 * this is done independently.
2395 */
2396 input = xmlNewEntityInputStream(ctxt, entity);
2397 if (xmlPushInput(ctxt, input) < 0)
2398 return;
2399
2400 /*
2401 * Get the 4 first bytes and decode the charset
2402 * if enc != XML_CHAR_ENCODING_NONE
2403 * plug some encoding conversion routines.
2404 * Note that, since we may have some non-UTF8
2405 * encoding (like UTF16, bug 135229), the 'length'
2406 * is not known, but we can calculate based upon
2407 * the amount of data in the buffer.
2408 */
2409 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
2410 if ((ctxt->input->end - ctxt->input->cur)>=4) {
2411 start[0] = RAW(*ctxt->input->cur);
2412 start[1] = NXT(1)ctxt->input->cur[(1)];
2413 start[2] = NXT(2)ctxt->input->cur[(2)];
2414 start[3] = NXT(3)ctxt->input->cur[(3)];
2415 enc = xmlDetectCharEncoding(start, 4);
2416 if (enc != XML_CHAR_ENCODING_NONE) {
2417 xmlSwitchEncoding(ctxt, enc);
2418 }
2419 }
2420
2421 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2422 (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )( ( ((unsigned char *) ctxt->input->cur)[ 0 ] == '<'
&& ((unsigned char *) ctxt->input->cur)[ 1 ] ==
'?' && ((unsigned char *) ctxt->input->cur)[ 2
] == 'x' && ((unsigned char *) ctxt->input->cur
)[ 3 ] == 'm' ) && ((unsigned char *) ctxt->input->
cur)[ 4 ] == 'l' )
) &&
2423 (IS_BLANK_CH(NXT(5))(((ctxt->input->cur[(5)]) == 0x20) || ((0x9 <= (ctxt
->input->cur[(5)])) && ((ctxt->input->cur
[(5)]) <= 0xa)) || ((ctxt->input->cur[(5)]) == 0xd))
)) {
2424 xmlParseTextDecl(ctxt);
2425 }
2426 } else {
2427 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
2428 "PEReference: %s is not a parameter entity\n",
2429 name);
2430 }
2431 }
2432 } else {
2433 xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL((void*)0));
2434 }
2435 }
2436}
2437
2438/*
2439 * Macro used to grow the current buffer.
2440 */
2441#define growBuffer(buffer, n){ xmlChar *tmp; buffer_size *= 2; buffer_size += n; tmp = (xmlChar
*) xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); if (tmp
== ((void*)0)) goto mem_error; buffer = tmp; }
{ \
2442 xmlChar *tmp; \
2443 buffer##_size *= 2; \
2444 buffer##_size += n; \
2445 tmp = (xmlChar *) \
2446 xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
2447 if (tmp == NULL((void*)0)) goto mem_error; \
2448 buffer = tmp; \
2449}
2450
2451/**
2452 * xmlStringLenDecodeEntities:
2453 * @ctxt: the parser context
2454 * @str: the input string
2455 * @len: the string length
2456 * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2457 * @end: an end marker xmlChar, 0 if none
2458 * @end2: an end marker xmlChar, 0 if none
2459 * @end3: an end marker xmlChar, 0 if none
2460 *
2461 * Takes a entity string content and process to do the adequate substitutions.
2462 *
2463 * [67] Reference ::= EntityRef | CharRef
2464 *
2465 * [69] PEReference ::= '%' Name ';'
2466 *
2467 * Returns A newly allocated string with the substitution done. The caller
2468 * must deallocate it !
2469 */
2470xmlChar *
2471xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2472 int what, xmlChar end, xmlChar end2, xmlChar end3) {
2473 xmlChar *buffer = NULL((void*)0);
2474 int buffer_size = 0;
2475
2476 xmlChar *current = NULL((void*)0);
2477 xmlChar *rep = NULL((void*)0);
2478 const xmlChar *last;
2479 xmlEntityPtr ent;
2480 int c,l;
2481 int nbchars = 0;
2482
2483 if ((ctxt == NULL((void*)0)) || (str == NULL((void*)0)) || (len < 0))
2484 return(NULL((void*)0));
2485 last = str + len;
2486
2487 if (((ctxt->depth > 40) &&
2488 ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2489 (ctxt->depth > 1024)) {
2490 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL((void*)0));
2491 return(NULL((void*)0));
2492 }
2493
2494 /*
2495 * allocate a translation buffer.
2496 */
2497 buffer_size = XML_PARSER_BIG_BUFFER_SIZE300;
2498 buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
2499 if (buffer == NULL((void*)0)) goto mem_error;
2500
2501 /*
2502 * OK loop until we reach one of the ending char or a size limit.
2503 * we are operating on already parsed values.
2504 */
2505 if (str < last)
2506 c = CUR_SCHAR(str, l)xmlStringCurrentChar(ctxt, str, &l);
2507 else
2508 c = 0;
2509 while ((c != 0) && (c != end) && /* non input consuming loop */
2510 (c != end2) && (c != end3)) {
2511
2512 if (c == 0) break;
2513 if ((c == '&') && (str[1] == '#')) {
2514 int val = xmlParseStringCharRef(ctxt, &str);
2515 if (val != 0) {
2516 COPY_BUF(0,buffer,nbchars,val)if (0 == 1) buffer[nbchars++] = (xmlChar) val; else nbchars +=
xmlCopyCharMultiByte(&buffer[nbchars],val)
;
2517 }
2518 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE100) {
2519 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2520 }
2521 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF1)) {
2522 if (xmlParserDebugEntities(*(__xmlParserDebugEntities())))
2523 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2524 "String decoding Entity Reference: %.30s\n",
2525 str);
2526 ent = xmlParseStringEntityRef(ctxt, &str);
2527 if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
2528 (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
2529 goto int_error;
2530 if (ent != NULL((void*)0))
2531 ctxt->nbentities += ent->checked;
2532 if ((ent != NULL((void*)0)) &&
2533 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2534 if (ent->content != NULL((void*)0)) {
2535 COPY_BUF(0,buffer,nbchars,ent->content[0])if (0 == 1) buffer[nbchars++] = (xmlChar) ent->content[0];
else nbchars += xmlCopyCharMultiByte(&buffer[nbchars],ent
->content[0])
;
2536 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE100) {
2537 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2538 }
2539 } else {
2540 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2541 "predefined entity has no content\n");
2542 }
2543 } else if ((ent != NULL((void*)0)) && (ent->content != NULL((void*)0))) {
2544 ctxt->depth++;
2545 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2546 0, 0, 0);
2547 ctxt->depth--;
2548
2549 if (rep != NULL((void*)0)) {
2550 current = rep;
2551 while (*current != 0) { /* non input consuming loop */
2552 buffer[nbchars++] = *current++;
2553 if (nbchars >
2554 buffer_size - XML_PARSER_BUFFER_SIZE100) {
2555 if (xmlParserEntityCheck(ctxt, nbchars, ent))
2556 goto int_error;
2557 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2558 }
2559 }
2560 xmlFree(rep);
2561 rep = NULL((void*)0);
2562 }
2563 } else if (ent != NULL((void*)0)) {
2564 int i = xmlStrlen(ent->name);
2565 const xmlChar *cur = ent->name;
2566
2567 buffer[nbchars++] = '&';
2568 if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE100) {
2569 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2570 }
2571 for (;i > 0;i--)
2572 buffer[nbchars++] = *cur++;
2573 buffer[nbchars++] = ';';
2574 }
2575 } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF2)) {
2576 if (xmlParserDebugEntities(*(__xmlParserDebugEntities())))
2577 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2578 "String decoding PE Reference: %.30s\n", str);
2579 ent = xmlParseStringPEReference(ctxt, &str);
2580 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
2581 goto int_error;
2582 if (ent != NULL((void*)0))
2583 ctxt->nbentities += ent->checked;
2584 if (ent != NULL((void*)0)) {
2585 if (ent->content == NULL((void*)0)) {
2586 xmlLoadEntityContent(ctxt, ent);
2587 }
2588 ctxt->depth++;
2589 rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2590 0, 0, 0);
2591 ctxt->depth--;
2592 if (rep != NULL((void*)0)) {
2593 current = rep;
2594 while (*current != 0) { /* non input consuming loop */
2595 buffer[nbchars++] = *current++;
2596 if (nbchars >
2597 buffer_size - XML_PARSER_BUFFER_SIZE100) {
2598 if (xmlParserEntityCheck(ctxt, nbchars, ent))
2599 goto int_error;
2600 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2601 }
2602 }
2603 xmlFree(rep);
2604 rep = NULL((void*)0);
2605 }
2606 }
2607 } else {
2608 COPY_BUF(l,buffer,nbchars,c)if (l == 1) buffer[nbchars++] = (xmlChar) c; else nbchars += xmlCopyCharMultiByte
(&buffer[nbchars],c)
;
2609 str += l;
2610 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE100) {
2611 growBuffer(buffer, XML_PARSER_BUFFER_SIZE){ xmlChar *tmp; buffer_size *= 2; buffer_size += 100; tmp = (
xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
if (tmp == ((void*)0)) goto mem_error; buffer = tmp; }
;
2612 }
2613 }
2614 if (str < last)
2615 c = CUR_SCHAR(str, l)xmlStringCurrentChar(ctxt, str, &l);
2616 else
2617 c = 0;
2618 }
2619 buffer[nbchars++] = 0;
2620 return(buffer);
2621
2622mem_error:
2623 xmlErrMemory(ctxt, NULL((void*)0));
2624int_error:
2625 if (rep != NULL((void*)0))
2626 xmlFree(rep);
2627 if (buffer != NULL((void*)0))
2628 xmlFree(buffer);
2629 return(NULL((void*)0));
2630}
2631
2632/**
2633 * xmlStringDecodeEntities:
2634 * @ctxt: the parser context
2635 * @str: the input string
2636 * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2637 * @end: an end marker xmlChar, 0 if none
2638 * @end2: an end marker xmlChar, 0 if none
2639 * @end3: an end marker xmlChar, 0 if none
2640 *
2641 * Takes a entity string content and process to do the adequate substitutions.
2642 *
2643 * [67] Reference ::= EntityRef | CharRef
2644 *
2645 * [69] PEReference ::= '%' Name ';'
2646 *
2647 * Returns A newly allocated string with the substitution done. The caller
2648 * must deallocate it !
2649 */
2650xmlChar *
2651xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2652 xmlChar end, xmlChar end2, xmlChar end3) {
2653 if ((ctxt == NULL((void*)0)) || (str == NULL((void*)0))) return(NULL((void*)0));
2654 return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2655 end, end2, end3));
2656}
2657
2658/************************************************************************
2659 * *
2660 * Commodity functions, cleanup needed ? *
2661 * *
2662 ************************************************************************/
2663
2664/**
2665 * areBlanks:
2666 * @ctxt: an XML parser context
2667 * @str: a xmlChar *
2668 * @len: the size of @str
2669 * @blank_chars: we know the chars are blanks
2670 *
2671 * Is this a sequence of blank chars that one can ignore ?
2672 *
2673 * Returns 1 if ignorable 0 otherwise.
2674 */
2675
2676static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2677 int blank_chars) {
2678 int i, ret;
2679 xmlNodePtr lastChild;
2680
2681 /*
2682 * Don't spend time trying to differentiate them, the same callback is
2683 * used !
2684 */
2685 if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2686 return(0);
2687
2688 /*
2689 * Check for xml:space value.
2690 */
2691 if ((ctxt->space == NULL((void*)0)) || (*(ctxt->space) == 1) ||
2692 (*(ctxt->space) == -2))
2693 return(0);
2694
2695 /*
2696 * Check that the string is made of blanks
2697 */
2698 if (blank_chars == 0) {
2699 for (i = 0;i < len;i++)
2700 if (!(IS_BLANK_CH(str[i])(((str[i]) == 0x20) || ((0x9 <= (str[i])) && ((str
[i]) <= 0xa)) || ((str[i]) == 0xd))
)) return(0);
2701 }
2702
2703 /*
2704 * Look if the element is mixed content in the DTD if available
2705 */
2706 if (ctxt->node == NULL((void*)0)) return(0);
2707 if (ctxt->myDoc != NULL((void*)0)) {
2708 ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2709 if (ret == 0) return(1);
2710 if (ret == 1) return(0);
2711 }
2712
2713 /*
2714 * Otherwise, heuristic :-\
2715 */
2716 if ((RAW(*ctxt->input->cur) != '<') && (RAW(*ctxt->input->cur) != 0xD)) return(0);
2717 if ((ctxt->node->children == NULL((void*)0)) &&
2718 (RAW(*ctxt->input->cur) == '<') && (NXT(1)ctxt->input->cur[(1)] == '/')) return(0);
2719
2720 lastChild = xmlGetLastChild(ctxt->node);
2721 if (lastChild == NULL((void*)0)) {
2722 if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2723 (ctxt->node->content != NULL((void*)0))) return(0);
2724 } else if (xmlNodeIsText(lastChild))
2725 return(0);
2726 else if ((ctxt->node->children != NULL((void*)0)) &&
2727 (xmlNodeIsText(ctxt->node->children)))
2728 return(0);
2729 return(1);
2730}
2731
2732/************************************************************************
2733 * *
2734 * Extra stuff for namespace support *
2735 * Relates to http://www.w3.org/TR/WD-xml-names *
2736 * *
2737 ************************************************************************/
2738
2739/**
2740 * xmlSplitQName:
2741 * @ctxt: an XML parser context
2742 * @name: an XML parser context
2743 * @prefix: a xmlChar **
2744 *
2745 * parse an UTF8 encoded XML qualified name string
2746 *
2747 * [NS 5] QName ::= (Prefix ':')? LocalPart
2748 *
2749 * [NS 6] Prefix ::= NCName
2750 *
2751 * [NS 7] LocalPart ::= NCName
2752 *
2753 * Returns the local part, and prefix is updated
2754 * to get the Prefix if any.
2755 */
2756
2757xmlChar *
2758xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2759 xmlChar buf[XML_MAX_NAMELEN100 + 5];
2760 xmlChar *buffer = NULL((void*)0);
2761 int len = 0;
2762 int max = XML_MAX_NAMELEN100;
2763 xmlChar *ret = NULL((void*)0);
2764 const xmlChar *cur = name;
2765 int c;
2766
2767 if (prefix == NULL((void*)0)) return(NULL((void*)0));
2768 *prefix = NULL((void*)0);
2769
2770 if (cur == NULL((void*)0)) return(NULL((void*)0));
2771
2772#ifndef XML_XML_NAMESPACE(const xmlChar *) "http://www.w3.org/XML/1998/namespace"
2773 /* xml: prefix is not really a namespace */
2774 if ((cur[0] == 'x') && (cur[1] == 'm') &&
2775 (cur[2] == 'l') && (cur[3] == ':'))
2776 return(xmlStrdup(name));
2777#endif
2778
2779 /* nasty but well=formed */
2780 if (cur[0] == ':')
2781 return(xmlStrdup(name));
2782
2783 c = *cur++;
2784 while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2785 buf[len++] = c;
2786 c = *cur++;
2787 }
2788 if (len >= max) {
2789 /*
2790 * Okay someone managed to make a huge name, so he's ready to pay
2791 * for the processing speed.
2792 */
2793 max = len * 2;
2794
2795 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2796 if (buffer == NULL((void*)0)) {
2797 xmlErrMemory(ctxt, NULL((void*)0));
2798 return(NULL((void*)0));
2799 }
2800 memcpy(buffer, buf, len);
2801 while ((c != 0) && (c != ':')) { /* tested bigname.xml */
2802 if (len + 10 > max) {
2803 xmlChar *tmp;
2804
2805 max *= 2;
2806 tmp = (xmlChar *) xmlRealloc(buffer,
2807 max * sizeof(xmlChar));
2808 if (tmp == NULL((void*)0)) {
2809 xmlFree(buffer);
2810 xmlErrMemory(ctxt, NULL((void*)0));
2811 return(NULL((void*)0));
2812 }
2813 buffer = tmp;
2814 }
2815 buffer[len++] = c;
2816 c = *cur++;
2817 }
2818 buffer[len] = 0;
2819 }
2820
2821 if ((c == ':') && (*cur == 0)) {
2822 if (buffer != NULL((void*)0))
2823 xmlFree(buffer);
2824 *prefix = NULL((void*)0);
2825 return(xmlStrdup(name));
2826 }
2827
2828 if (buffer == NULL((void*)0))
2829 ret = xmlStrndup(buf, len);
2830 else {
2831 ret = buffer;
2832 buffer = NULL((void*)0);
2833 max = XML_MAX_NAMELEN100;
2834 }
2835
2836
2837 if (c == ':') {
2838 c = *cur;
2839 *prefix = ret;
2840 if (c == 0) {
2841 return(xmlStrndup(BAD_CAST(xmlChar *) "", 0));
2842 }
2843 len = 0;
2844
2845 /*
2846 * Check that the first character is proper to start
2847 * a new name
2848 */
2849 if (!(((c >= 0x61) && (c <= 0x7A)) ||
2850 ((c >= 0x41) && (c <= 0x5A)) ||
2851 (c == '_') || (c == ':'))) {
2852 int l;
2853 int first = CUR_SCHAR(cur, l)xmlStringCurrentChar(ctxt, cur, &l);
2854
2855 if (!IS_LETTER(first)((((first) < 0x100) ? (((0x41 <= ((first))) && (
((first)) <= 0x5a)) || ((0x61 <= ((first))) && (
((first)) <= 0x7a)) || ((0xc0 <= ((first))) && (
((first)) <= 0xd6)) || ((0xd8 <= ((first))) && (
((first)) <= 0xf6)) || (0xf8 <= ((first)))) : xmlCharInRange
((first), &xmlIsBaseCharGroup)) || (((first) < 0x100) ?
0 : (((0x4e00 <= (first)) && ((first) <= 0x9fa5
)) || ((first) == 0x3007) || ((0x3021 <= (first)) &&
((first) <= 0x3029)))))
&& (first != '_')) {
2856 xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
2857 "Name %s is not XML Namespace compliant\n",
2858 name);
2859 }
2860 }
2861 cur++;
2862
2863 while ((c != 0) && (len < max)) { /* tested bigname2.xml */
2864 buf[len++] = c;
2865 c = *cur++;
2866 }
2867 if (len >= max) {
2868 /*
2869 * Okay someone managed to make a huge name, so he's ready to pay
2870 * for the processing speed.
2871 */
2872 max = len * 2;
2873
2874 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
2875 if (buffer == NULL((void*)0)) {
2876 xmlErrMemory(ctxt, NULL((void*)0));
2877 return(NULL((void*)0));
2878 }
2879 memcpy(buffer, buf, len);
2880 while (c != 0) { /* tested bigname2.xml */
2881 if (len + 10 > max) {
2882 xmlChar *tmp;
2883
2884 max *= 2;
2885 tmp = (xmlChar *) xmlRealloc(buffer,
2886 max * sizeof(xmlChar));
2887 if (tmp == NULL((void*)0)) {
2888 xmlErrMemory(ctxt, NULL((void*)0));
2889 xmlFree(buffer);
2890 return(NULL((void*)0));
2891 }
2892 buffer = tmp;
2893 }
2894 buffer[len++] = c;
2895 c = *cur++;
2896 }
2897 buffer[len] = 0;
2898 }
2899
2900 if (buffer == NULL((void*)0))
2901 ret = xmlStrndup(buf, len);
2902 else {
2903 ret = buffer;
2904 }
2905 }
2906
2907 return(ret);
2908}
2909
2910/************************************************************************
2911 * *
2912 * The parser itself *
2913 * Relates to http://www.w3.org/TR/REC-xml *
2914 * *
2915 ************************************************************************/
2916
2917/************************************************************************
2918 * *
2919 * Routines to parse Name, NCName and NmToken *
2920 * *
2921 ************************************************************************/
2922#ifdef DEBUG
2923static unsigned long nbParseName = 0;
2924static unsigned long nbParseNmToken = 0;
2925static unsigned long nbParseNCName = 0;
2926static unsigned long nbParseNCNameComplex = 0;
2927static unsigned long nbParseNameComplex = 0;
2928static unsigned long nbParseStringName = 0;
2929#endif
2930
2931/*
2932 * The two following functions are related to the change of accepted
2933 * characters for Name and NmToken in the Revision 5 of XML-1.0
2934 * They correspond to the modified production [4] and the new production [4a]
2935 * changes in that revision. Also note that the macros used for the
2936 * productions Letter, Digit, CombiningChar and Extender are not needed
2937 * anymore.
2938 * We still keep compatibility to pre-revision5 parsing semantic if the
2939 * new XML_PARSE_OLD10 option is given to the parser.
2940 */
2941static int
2942xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
2943 if ((ctxt->options & XML_PARSE_OLD10) == 0) {
2944 /*
2945 * Use the new checks of production [4] [4a] amd [5] of the
2946 * Update 5 of XML-1.0
2947 */
2948 if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
2949 (((c >= 'a') && (c <= 'z')) ||
2950 ((c >= 'A') && (c <= 'Z')) ||
2951 (c == '_') || (c == ':') ||
2952 ((c >= 0xC0) && (c <= 0xD6)) ||
2953 ((c >= 0xD8) && (c <= 0xF6)) ||
2954 ((c >= 0xF8) && (c <= 0x2FF)) ||
2955 ((c >= 0x370) && (c <= 0x37D)) ||
2956 ((c >= 0x37F) && (c <= 0x1FFF)) ||
2957 ((c >= 0x200C) && (c <= 0x200D)) ||
2958 ((c >= 0x2070) && (c <= 0x218F)) ||
2959 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
2960 ((c >= 0x3001) && (c <= 0xD7FF)) ||
2961 ((c >= 0xF900) && (c <= 0xFDCF)) ||
2962 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
2963 ((c >= 0x10000) && (c <= 0xEFFFF))))
2964 return(1);
2965 } else {
2966 if (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| (c == '_') || (c == ':'))
2967 return(1);
2968 }
2969 return(0);
2970}
2971
2972static int
2973xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
2974 if ((ctxt->options & XML_PARSE_OLD10) == 0) {
2975 /*
2976 * Use the new checks of production [4] [4a] amd [5] of the
2977 * Update 5 of XML-1.0
2978 */
2979 if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
2980 (((c >= 'a') && (c <= 'z')) ||
2981 ((c >= 'A') && (c <= 'Z')) ||
2982 ((c >= '0') && (c <= '9')) || /* !start */
2983 (c == '_') || (c == ':') ||
2984 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
2985 ((c >= 0xC0) && (c <= 0xD6)) ||
2986 ((c >= 0xD8) && (c <= 0xF6)) ||
2987 ((c >= 0xF8) && (c <= 0x2FF)) ||
2988 ((c >= 0x300) && (c <= 0x36F)) || /* !start */
2989 ((c >= 0x370) && (c <= 0x37D)) ||
2990 ((c >= 0x37F) && (c <= 0x1FFF)) ||
2991 ((c >= 0x200C) && (c <= 0x200D)) ||
2992 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
2993 ((c >= 0x2070) && (c <= 0x218F)) ||
2994 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
2995 ((c >= 0x3001) && (c <= 0xD7FF)) ||
2996 ((c >= 0xF900) && (c <= 0xFDCF)) ||
2997 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
2998 ((c >= 0x10000) && (c <= 0xEFFFF))))
2999 return(1);
3000 } else {
3001 if ((IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) || (IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
) ||
3002 (c == '.') || (c == '-') ||
3003 (c == '_') || (c == ':') ||
3004 (IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
) ||
3005 (IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
))
3006 return(1);
3007 }
3008 return(0);
3009}
3010
3011static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3012 int *len, int *alloc, int normalize);
3013
3014static const xmlChar *
3015xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3016 int len = 0, l;
3017 int c;
3018 int count = 0;
3019
3020#ifdef DEBUG
3021 nbParseNameComplex++;
3022#endif
3023
3024 /*
3025 * Handler for more complex cases
3026 */
3027 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3028 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3029 if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3030 /*
3031 * Use the new checks of production [4] [4a] amd [5] of the
3032 * Update 5 of XML-1.0
3033 */
3034 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3035 (!(((c >= 'a') && (c <= 'z')) ||
3036 ((c >= 'A') && (c <= 'Z')) ||
3037 (c == '_') || (c == ':') ||
3038 ((c >= 0xC0) && (c <= 0xD6)) ||
3039 ((c >= 0xD8) && (c <= 0xF6)) ||
3040 ((c >= 0xF8) && (c <= 0x2FF)) ||
3041 ((c >= 0x370) && (c <= 0x37D)) ||
3042 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3043 ((c >= 0x200C) && (c <= 0x200D)) ||
3044 ((c >= 0x2070) && (c <= 0x218F)) ||
3045 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3046 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3047 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3048 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3049 ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3050 return(NULL((void*)0));
3051 }
3052 len += l;
3053 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3054 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3055 while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3056 (((c >= 'a') && (c <= 'z')) ||
3057 ((c >= 'A') && (c <= 'Z')) ||
3058 ((c >= '0') && (c <= '9')) || /* !start */
3059 (c == '_') || (c == ':') ||
3060 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3061 ((c >= 0xC0) && (c <= 0xD6)) ||
3062 ((c >= 0xD8) && (c <= 0xF6)) ||
3063 ((c >= 0xF8) && (c <= 0x2FF)) ||
3064 ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3065 ((c >= 0x370) && (c <= 0x37D)) ||
3066 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3067 ((c >= 0x200C) && (c <= 0x200D)) ||
3068 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3069 ((c >= 0x2070) && (c <= 0x218F)) ||
3070 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3071 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3072 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3073 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3074 ((c >= 0x10000) && (c <= 0xEFFFF))
3075 )) {
3076 if (count++ > 100) {
3077 count = 0;
3078 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3079 }
3080 len += l;
3081 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3082 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3083 }
3084 } else {
3085 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3086 (!IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
&& (c != '_') &&
3087 (c != ':'))) {
3088 return(NULL((void*)0));
3089 }
3090 len += l;
3091 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3092 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3093
3094 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3095 ((IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) || (IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
) ||
3096 (c == '.') || (c == '-') ||
3097 (c == '_') || (c == ':') ||
3098 (IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
) ||
3099 (IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
))) {
3100 if (count++ > 100) {
3101 count = 0;
3102 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3103 }
3104 len += l;
3105 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3106 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3107 }
3108 }
3109 if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3110 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3111 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3112}
3113
3114/**
3115 * xmlParseName:
3116 * @ctxt: an XML parser context
3117 *
3118 * parse an XML name.
3119 *
3120 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3121 * CombiningChar | Extender
3122 *
3123 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3124 *
3125 * [6] Names ::= Name (#x20 Name)*
3126 *
3127 * Returns the Name parsed or NULL
3128 */
3129
3130const xmlChar *
3131xmlParseName(xmlParserCtxtPtr ctxt) {
3132 const xmlChar *in;
3133 const xmlChar *ret;
3134 int count = 0;
3135
3136 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3137
3138#ifdef DEBUG
3139 nbParseName++;
3140#endif
3141
3142 /*
3143 * Accelerator for simple ASCII names
3144 */
3145 in = ctxt->input->cur;
3146 if (((*in >= 0x61) && (*in <= 0x7A)) ||
3147 ((*in >= 0x41) && (*in <= 0x5A)) ||
3148 (*in == '_') || (*in == ':')) {
3149 in++;
3150 while (((*in >= 0x61) && (*in <= 0x7A)) ||
3151 ((*in >= 0x41) && (*in <= 0x5A)) ||
3152 ((*in >= 0x30) && (*in <= 0x39)) ||
3153 (*in == '_') || (*in == '-') ||
3154 (*in == ':') || (*in == '.'))
3155 in++;
3156 if ((*in > 0) && (*in < 0x80)) {
3157 count = in - ctxt->input->cur;
3158 ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3159 ctxt->input->cur = in;
3160 ctxt->nbChars += count;
3161 ctxt->input->col += count;
3162 if (ret == NULL((void*)0))
3163 xmlErrMemory(ctxt, NULL((void*)0));
3164 return(ret);
3165 }
3166 }
3167 /* accelerator for special cases */
3168 return(xmlParseNameComplex(ctxt));
3169}
3170
3171static const xmlChar *
3172xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3173 int len = 0, l;
3174 int c;
3175 int count = 0;
3176
3177#ifdef DEBUG
3178 nbParseNCNameComplex++;
3179#endif
3180
3181 /*
3182 * Handler for more complex cases
3183 */
3184 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3185 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3186 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3187 (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3188 return(NULL((void*)0));
3189 }
3190
3191 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3192 (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3193 if (count++ > 100) {
3194 count = 0;
3195 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3196 }
3197 len += l;
3198 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3199 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3200 }
3201 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3202}
3203
3204/**
3205 * xmlParseNCName:
3206 * @ctxt: an XML parser context
3207 * @len: lenght of the string parsed
3208 *
3209 * parse an XML name.
3210 *
3211 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3212 * CombiningChar | Extender
3213 *
3214 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3215 *
3216 * Returns the Name parsed or NULL
3217 */
3218
3219static const xmlChar *
3220xmlParseNCName(xmlParserCtxtPtr ctxt) {
3221 const xmlChar *in;
3222 const xmlChar *ret;
3223 int count = 0;
3224
3225#ifdef DEBUG
3226 nbParseNCName++;
3227#endif
3228
3229 /*
3230 * Accelerator for simple ASCII names
3231 */
3232 in = ctxt->input->cur;
3233 if (((*in >= 0x61) && (*in <= 0x7A)) ||
3234 ((*in >= 0x41) && (*in <= 0x5A)) ||
3235 (*in == '_')) {
3236 in++;
3237 while (((*in >= 0x61) && (*in <= 0x7A)) ||
3238 ((*in >= 0x41) && (*in <= 0x5A)) ||
3239 ((*in >= 0x30) && (*in <= 0x39)) ||
3240 (*in == '_') || (*in == '-') ||
3241 (*in == '.'))
3242 in++;
3243 if ((*in > 0) && (*in < 0x80)) {
3244 count = in - ctxt->input->cur;
3245 ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3246 ctxt->input->cur = in;
3247 ctxt->nbChars += count;
3248 ctxt->input->col += count;
3249 if (ret == NULL((void*)0)) {
3250 xmlErrMemory(ctxt, NULL((void*)0));
3251 }
3252 return(ret);
3253 }
3254 }
3255 return(xmlParseNCNameComplex(ctxt));
3256}
3257
3258/**
3259 * xmlParseNameAndCompare:
3260 * @ctxt: an XML parser context
3261 *
3262 * parse an XML name and compares for match
3263 * (specialized for endtag parsing)
3264 *
3265 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3266 * and the name for mismatch
3267 */
3268
3269static const xmlChar *
3270xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3271 register const xmlChar *cmp = other;
3272 register const xmlChar *in;
3273 const xmlChar *ret;
3274
3275 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3276
3277 in = ctxt->input->cur;
3278 while (*in != 0 && *in == *cmp) {
3279 ++in;
3280 ++cmp;
3281 ctxt->input->col++;
3282 }
3283 if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in)(((*in) == 0x20) || ((0x9 <= (*in)) && ((*in) <=
0xa)) || ((*in) == 0xd))
)) {
3284 /* success */
3285 ctxt->input->cur = in;
3286 return (const xmlChar*) 1;
3287 }
3288 /* failure (or end of input buffer), check with full function */
3289 ret = xmlParseName (ctxt);
3290 /* strings coming from the dictionnary direct compare possible */
3291 if (ret == other) {
3292 return (const xmlChar*) 1;
3293 }
3294 return ret;
3295}
3296
3297/**
3298 * xmlParseStringName:
3299 * @ctxt: an XML parser context
3300 * @str: a pointer to the string pointer (IN/OUT)
3301 *
3302 * parse an XML name.
3303 *
3304 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3305 * CombiningChar | Extender
3306 *
3307 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3308 *
3309 * [6] Names ::= Name (#x20 Name)*
3310 *
3311 * Returns the Name parsed or NULL. The @str pointer
3312 * is updated to the current location in the string.
3313 */
3314
3315static xmlChar *
3316xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3317 xmlChar buf[XML_MAX_NAMELEN100 + 5];
3318 const xmlChar *cur = *str;
3319 int len = 0, l;
3320 int c;
3321
3322#ifdef DEBUG
3323 nbParseStringName++;
3324#endif
3325
3326 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(ctxt, cur, &l);
3327 if (!xmlIsNameStartChar(ctxt, c)) {
3328 return(NULL((void*)0));
3329 }
3330
3331 COPY_BUF(l,buf,len,c)if (l == 1) buf[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buf[len],c)
;
3332 cur += l;
3333 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(ctxt, cur, &l);
3334 while (xmlIsNameChar(ctxt, c)) {
3335 COPY_BUF(l,buf,len,c)if (l == 1) buf[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buf[len],c)
;
3336 cur += l;
3337 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(ctxt, cur, &l);
3338 if (len >= XML_MAX_NAMELEN100) { /* test bigentname.xml */
3339 /*
3340 * Okay someone managed to make a huge name, so he's ready to pay
3341 * for the processing speed.
3342 */
3343 xmlChar *buffer;
3344 int max = len * 2;
3345
3346 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3347 if (buffer == NULL((void*)0)) {
3348 xmlErrMemory(ctxt, NULL((void*)0));
3349 return(NULL((void*)0));
3350 }
3351 memcpy(buffer, buf, len);
3352 while (xmlIsNameChar(ctxt, c)) {
3353 if (len + 10 > max) {
3354 xmlChar *tmp;
3355 max *= 2;
3356 tmp = (xmlChar *) xmlRealloc(buffer,
3357 max * sizeof(xmlChar));
3358 if (tmp == NULL((void*)0)) {
3359 xmlErrMemory(ctxt, NULL((void*)0));
3360 xmlFree(buffer);
3361 return(NULL((void*)0));
3362 }
3363 buffer = tmp;
3364 }
3365 COPY_BUF(l,buffer,len,c)if (l == 1) buffer[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buffer[len],c)
;
3366 cur += l;
3367 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(ctxt, cur, &l);
3368 }
3369 buffer[len] = 0;
3370 *str = cur;
3371 return(buffer);
3372 }
3373 }
3374 *str = cur;
3375 return(xmlStrndup(buf, len));
3376}
3377
3378/**
3379 * xmlParseNmtoken:
3380 * @ctxt: an XML parser context
3381 *
3382 * parse an XML Nmtoken.
3383 *
3384 * [7] Nmtoken ::= (NameChar)+
3385 *
3386 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3387 *
3388 * Returns the Nmtoken parsed or NULL
3389 */
3390
3391xmlChar *
3392xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3393 xmlChar buf[XML_MAX_NAMELEN100 + 5];
3394 int len = 0, l;
3395 int c;
3396 int count = 0;
3397
3398#ifdef DEBUG
3399 nbParseNmToken++;
3400#endif
3401
3402 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3403 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3404
3405 while (xmlIsNameChar(ctxt, c)) {
3406 if (count++ > 100) {
3407 count = 0;
3408 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3409 }
3410 COPY_BUF(l,buf,len,c)if (l == 1) buf[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buf[len],c)
;
3411 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3412 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3413 if (len >= XML_MAX_NAMELEN100) {
3414 /*
3415 * Okay someone managed to make a huge token, so he's ready to pay
3416 * for the processing speed.
3417 */
3418 xmlChar *buffer;
3419 int max = len * 2;
3420
3421 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3422 if (buffer == NULL((void*)0)) {
3423 xmlErrMemory(ctxt, NULL((void*)0));
3424 return(NULL((void*)0));
3425 }
3426 memcpy(buffer, buf, len);
3427 while (xmlIsNameChar(ctxt, c)) {
3428 if (count++ > 100) {
3429 count = 0;
3430 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3431 }
3432 if (len + 10 > max) {
3433 xmlChar *tmp;
3434
3435 max *= 2;
3436 tmp = (xmlChar *) xmlRealloc(buffer,
3437 max * sizeof(xmlChar));
3438 if (tmp == NULL((void*)0)) {
3439 xmlErrMemory(ctxt, NULL((void*)0));
3440 xmlFree(buffer);
3441 return(NULL((void*)0));
3442 }
3443 buffer = tmp;
3444 }
3445 COPY_BUF(l,buffer,len,c)if (l == 1) buffer[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buffer[len],c)
;
3446 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3447 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3448 }
3449 buffer[len] = 0;
3450 return(buffer);
3451 }
3452 }
3453 if (len == 0)
3454 return(NULL((void*)0));
3455 return(xmlStrndup(buf, len));
3456}
3457
3458/**
3459 * xmlParseEntityValue:
3460 * @ctxt: an XML parser context
3461 * @orig: if non-NULL store a copy of the original entity value
3462 *
3463 * parse a value for ENTITY declarations
3464 *
3465 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3466 * "'" ([^%&'] | PEReference | Reference)* "'"
3467 *
3468 * Returns the EntityValue parsed with reference substituted or NULL
3469 */
3470
3471xmlChar *
3472xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3473 xmlChar *buf = NULL((void*)0);
3474 int len = 0;
3475 int size = XML_PARSER_BUFFER_SIZE100;
3476 int c, l;
3477 xmlChar stop;
3478 xmlChar *ret = NULL((void*)0);
3479 const xmlChar *cur = NULL((void*)0);
3480 xmlParserInputPtr input;
3481
3482 if (RAW(*ctxt->input->cur) == '"') stop = '"';
3483 else if (RAW(*ctxt->input->cur) == '\'') stop = '\'';
3484 else {
3485 xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL((void*)0));
3486 return(NULL((void*)0));
3487 }
3488 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3489 if (buf == NULL((void*)0)) {
3490 xmlErrMemory(ctxt, NULL((void*)0));
3491 return(NULL((void*)0));
3492 }
3493
3494 /*
3495 * The content of the entity definition is copied in a buffer.
3496 */
3497
3498 ctxt->instate = XML_PARSER_ENTITY_VALUE;
3499 input = ctxt->input;
3500 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3501 NEXTxmlNextChar(ctxt);
3502 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3503 /*
3504 * NOTE: 4.4.5 Included in Literal
3505 * When a parameter entity reference appears in a literal entity
3506 * value, ... a single or double quote character in the replacement
3507 * text is always treated as a normal data character and will not
3508 * terminate the literal.
3509 * In practice it means we stop the loop only when back at parsing
3510 * the initial entity and the quote is found
3511 */
3512 while ((IS_CHAR(c)(((c) < 0x100) ? (((0x9 <= ((c))) && (((c)) <=
0xa)) || (((c)) == 0xd) || (0x20 <= ((c)))) : (((0x100 <=
(c)) && ((c) <= 0xd7ff)) || ((0xe000 <= (c)) &&
((c) <= 0xfffd)) || ((0x10000 <= (c)) && ((c) <=
0x10ffff))))
) && ((c != stop) || /* checked */
3513 (ctxt->input != input))) {
3514 if (len + 5 >= size) {
3515 xmlChar *tmp;
3516
3517 size *= 2;
3518 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
3519 if (tmp == NULL((void*)0)) {
3520 xmlErrMemory(ctxt, NULL((void*)0));
3521 xmlFree(buf);
3522 return(NULL((void*)0));
3523 }
3524 buf = tmp;
3525 }
3526 COPY_BUF(l,buf,len,c)if (l == 1) buf[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buf[len],c)
;
3527 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3528 /*
3529 * Pop-up of finished entities.
3530 */
3531 while ((RAW(*ctxt->input->cur) == 0) && (ctxt->inputNr > 1)) /* non input consuming */
3532 xmlPopInput(ctxt);
3533
3534 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3535 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3536 if (c == 0) {
3537 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3538 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3539 }
3540 }
3541 buf[len] = 0;
3542
3543 /*
3544 * Raise problem w.r.t. '&' and '%' being used in non-entities
3545 * reference constructs. Note Charref will be handled in
3546 * xmlStringDecodeEntities()
3547 */
3548 cur = buf;
3549 while (*cur != 0) { /* non input consuming */
3550 if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3551 xmlChar *name;
3552 xmlChar tmp = *cur;
3553
3554 cur++;
3555 name = xmlParseStringName(ctxt, &cur);
3556 if ((name == NULL((void*)0)) || (*cur != ';')) {
3557 xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3558 "EntityValue: '%c' forbidden except for entities references\n",
3559 tmp);
3560 }
3561 if ((tmp == '%') && (ctxt->inSubset == 1) &&
3562 (ctxt->inputNr == 1)) {
3563 xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL((void*)0));
3564 }
3565 if (name != NULL((void*)0))
3566 xmlFree(name);
3567 if (*cur == 0)
3568 break;
3569 }
3570 cur++;
3571 }
3572
3573 /*
3574 * Then PEReference entities are substituted.
3575 */
3576 if (c != stop) {
3577 xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL((void*)0));
3578 xmlFree(buf);
3579 } else {
3580 NEXTxmlNextChar(ctxt);
3581 /*
3582 * NOTE: 4.4.7 Bypassed
3583 * When a general entity reference appears in the EntityValue in
3584 * an entity declaration, it is bypassed and left as is.
3585 * so XML_SUBSTITUTE_REF is not set here.
3586 */
3587 ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF2,
3588 0, 0, 0);
3589 if (orig != NULL((void*)0))
3590 *orig = buf;
3591 else
3592 xmlFree(buf);
3593 }
3594
3595 return(ret);
3596}
3597
3598/**
3599 * xmlParseAttValueComplex:
3600 * @ctxt: an XML parser context
3601 * @len: the resulting attribute len
3602 * @normalize: wether to apply the inner normalization
3603 *
3604 * parse a value for an attribute, this is the fallback function
3605 * of xmlParseAttValue() when the attribute parsing requires handling
3606 * of non-ASCII characters, or normalization compaction.
3607 *
3608 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3609 */
3610static xmlChar *
3611xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3612 xmlChar limit = 0;
3613 xmlChar *buf = NULL((void*)0);
3614 xmlChar *rep = NULL((void*)0);
3615 int len = 0;
3616 int buf_size = 0;
3617 int c, l, in_space = 0;
3618 xmlChar *current = NULL((void*)0);
3619 xmlEntityPtr ent;
3620
3621 if (NXT(0)ctxt->input->cur[(0)] == '"') {
3622 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3623 limit = '"';
3624 NEXTxmlNextChar(ctxt);
3625 } else if (NXT(0)ctxt->input->cur[(0)] == '\'') {
3626 limit = '\'';
3627 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3628 NEXTxmlNextChar(ctxt);
3629 } else {
3630 xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL((void*)0));
3631 return(NULL((void*)0));
3632 }
3633
3634 /*
3635 * allocate a translation buffer.
3636 */
3637 buf_size = XML_PARSER_BUFFER_SIZE100;
3638 buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
3639 if (buf == NULL((void*)0)) goto mem_error;
3640
3641 /*
3642 * OK loop until we reach one of the ending char or a size limit.
3643 */
3644 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3645 while ((NXT(0)ctxt->input->cur[(0)] != limit) && /* checked */
3646 (IS_CHAR(c)(((c) < 0x100) ? (((0x9 <= ((c))) && (((c)) <=
0xa)) || (((c)) == 0xd) || (0x20 <= ((c)))) : (((0x100 <=
(c)) && ((c) <= 0xd7ff)) || ((0xe000 <= (c)) &&
((c) <= 0xfffd)) || ((0x10000 <= (c)) && ((c) <=
0x10ffff))))
) && (c != '<')) {
3647 if (c == 0) break;
3648 if (c == '&') {
3649 in_space = 0;
3650 if (NXT(1)ctxt->input->cur[(1)] == '#') {
3651 int val = xmlParseCharRef(ctxt);
3652
3653 if (val == '&') {
3654 if (ctxt->replaceEntities) {
3655 if (len > buf_size - 10) {
3656 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3657 }
3658 buf[len++] = '&';
3659 } else {
3660 /*
3661 * The reparsing will be done in xmlStringGetNodeList()
3662 * called by the attribute() function in SAX.c
3663 */
3664 if (len > buf_size - 10) {
3665 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3666 }
3667 buf[len++] = '&';
3668 buf[len++] = '#';
3669 buf[len++] = '3';
3670 buf[len++] = '8';
3671 buf[len++] = ';';
3672 }
3673 } else if (val != 0) {
3674 if (len > buf_size - 10) {
3675 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3676 }
3677 len += xmlCopyChar(0, &buf[len], val);
3678 }
3679 } else {
3680 ent = xmlParseEntityRef(ctxt);
3681 ctxt->nbentities++;
3682 if (ent != NULL((void*)0))
3683 ctxt->nbentities += ent->owner;
3684 if ((ent != NULL((void*)0)) &&
3685 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
3686 if (len > buf_size - 10) {
3687 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3688 }
3689 if ((ctxt->replaceEntities == 0) &&
3690 (ent->content[0] == '&')) {
3691 buf[len++] = '&';
3692 buf[len++] = '#';
3693 buf[len++] = '3';
3694 buf[len++] = '8';
3695 buf[len++] = ';';
3696 } else {
3697 buf[len++] = ent->content[0];
3698 }
3699 } else if ((ent != NULL((void*)0)) &&
3700 (ctxt->replaceEntities != 0)) {
3701 if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
3702 rep = xmlStringDecodeEntities(ctxt, ent->content,
3703 XML_SUBSTITUTE_REF1,
3704 0, 0, 0);
3705 if (rep != NULL((void*)0)) {
3706 current = rep;
3707 while (*current != 0) { /* non input consuming */
3708 if ((*current == 0xD) || (*current == 0xA) ||
3709 (*current == 0x9)) {
3710 buf[len++] = 0x20;
3711 current++;
3712 } else
3713 buf[len++] = *current++;
3714 if (len > buf_size - 10) {
3715 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3716 }
3717 }
3718 xmlFree(rep);
3719 rep = NULL((void*)0);
3720 }
3721 } else {
3722 if (len > buf_size - 10) {
3723 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3724 }
3725 if (ent->content != NULL((void*)0))
3726 buf[len++] = ent->content[0];
3727 }
3728 } else if (ent != NULL((void*)0)) {
3729 int i = xmlStrlen(ent->name);
3730 const xmlChar *cur = ent->name;
3731
3732 /*
3733 * This may look absurd but is needed to detect
3734 * entities problems
3735 */
3736 if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
3737 (ent->content != NULL((void*)0))) {
3738 rep = xmlStringDecodeEntities(ctxt, ent->content,
3739 XML_SUBSTITUTE_REF1, 0, 0, 0);
3740 if (rep != NULL((void*)0)) {
3741 xmlFree(rep);
3742 rep = NULL((void*)0);
3743 }
3744 }
3745
3746 /*
3747 * Just output the reference
3748 */
3749 buf[len++] = '&';
3750 while (len > buf_size - i - 10) {
3751 growBuffer(buf, i + 10){ xmlChar *tmp; buf_size *= 2; buf_size += i + 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3752 }
3753 for (;i > 0;i--)
3754 buf[len++] = *cur++;
3755 buf[len++] = ';';
3756 }
3757 }
3758 } else {
3759 if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
3760 if ((len != 0) || (!normalize)) {
3761 if ((!normalize) || (!in_space)) {
3762 COPY_BUF(l,buf,len,0x20)if (l == 1) buf[len++] = (xmlChar) 0x20; else len += xmlCopyCharMultiByte
(&buf[len],0x20)
;
3763 while (len > buf_size - 10) {
3764 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3765 }
3766 }
3767 in_space = 1;
3768 }
3769 } else {
3770 in_space = 0;
3771 COPY_BUF(l,buf,len,c)if (l == 1) buf[len++] = (xmlChar) c; else len += xmlCopyCharMultiByte
(&buf[len],c)
;
3772 if (len > buf_size - 10) {
3773 growBuffer(buf, 10){ xmlChar *tmp; buf_size *= 2; buf_size += 10; tmp = (xmlChar
*) xmlRealloc(buf, buf_size * sizeof(xmlChar)); if (tmp == (
(void*)0)) goto mem_error; buf = tmp; }
;
3774 }
3775 }
3776 NEXTL(l)do { if (*(ctxt->input->cur) == '\n') { ctxt->input->
line++; ctxt->input->col = 1; } else ctxt->input->
col++; ctxt->input->cur += l; if (*ctxt->input->cur
== '%') xmlParserHandlePEReference(ctxt); } while (0)
;
3777 }
3778 GROWif ((ctxt->progressive == 0) && (ctxt->input->
end - ctxt->input->cur < 250)) xmlGROW (ctxt);
;
3779 c = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3780 }
3781 if ((in_space) && (normalize)) {
3782 while (buf[len - 1] == 0x20) len--;
3783 }
3784 buf[len] = 0;
3785 if (RAW(*ctxt->input->cur) == '<') {
3786 xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL((void*)0));
3787 } else if (RAW(*ctxt->input->cur) != limit) {
3788 if ((c != 0) && (!IS_CHAR(c)(((c) < 0x100) ? (((0x9 <= ((c))) && (((c)) <=
0xa)) || (((c)) == 0xd) || (0x20 <= ((c)))) : (((0x100 <=
(c)) && ((c) <= 0xd7ff)) || ((0xe000 <= (c)) &&
((c) <= 0xfffd)) || ((0x10000 <= (c)) && ((c) <=
0x10ffff))))
)) {
3789 xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
3790 "invalid character in attribute value\n");
3791 } else {
3792 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
3793 "AttValue: ' expected\n");
3794 }
3795 } else
3796 NEXTxmlNextChar(ctxt);
3797 if (attlen != NULL((void*)0)) *attlen = len;
3798 return(buf);
3799
3800mem_error:
3801 xmlErrMemory(ctxt, NULL((void*)0));
3802 if (buf != NULL((void*)0))
3803 xmlFree(buf);
3804 if (rep != NULL((void*)0))
3805 xmlFree(rep);
3806 return(NULL((void*)0));
3807}
3808
3809/**
3810 * xmlParseAttValue:
3811 * @ctxt: an XML parser context
3812 *
3813 * parse a value for an attribute
3814 * Note: the parser won't do substitution of entities here, this
3815 * will be handled later in xmlStringGetNodeList
3816 *
3817 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
3818 * "'" ([^<&'] | Reference)* "'"
3819 *
3820 * 3.3.3 Attribute-Value Normalization:
3821 * Before the value of an attribute is passed to the application or
3822 * checked for validity, the XML processor must normalize it as follows:
3823 * - a character reference is processed by appending the referenced
3824 * character to the attribute value
3825 * - an entity reference is processed by recursively processing the
3826 * replacement text of the entity
3827 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
3828 * appending #x20 to the normalized value, except that only a single
3829 * #x20 is appended for a "#xD#xA" sequence that is part of an external
3830 * parsed entity or the literal entity value of an internal parsed entity
3831 * - other characters are processed by appending them to the normalized value
3832 * If the declared value is not CDATA, then the XML processor must further
3833 * process the normalized attribute value by discarding any leading and
3834 * trailing space (#x20) characters, and by replacing sequences of space
3835 * (#x20) characters by a single space (#x20) character.
3836 * All attributes for which no declaration has been read should be treated
3837 * by a non-validating parser as if declared CDATA.
3838 *
3839 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3840 */
3841
3842
3843xmlChar *
3844xmlParseAttValue(xmlParserCtxtPtr ctxt) {
3845 if ((ctxt == NULL((void*)0)) || (ctxt->input == NULL((void*)0))) return(NULL((void*)0));
3846 return(xmlParseAttValueInternal(ctxt, NULL((void*)0), NULL((void*)0), 0));
3847}
3848
3849/**
3850 * xmlParseSystemLiteral:
3851 * @ctxt: an XML parser context
3852 *
3853 * parse an XML Literal
3854 *
3855 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
3856 *
3857 * Returns the SystemLiteral parsed or NULL
3858 */
3859
3860xmlChar *
3861xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
3862 xmlChar *buf = NULL((void*)0);
3863 int len = 0;
3864 int size = XML_PARSER_BUFFER_SIZE100;
3865 int cur, l;
3866 xmlChar stop;
3867 int state = ctxt->instate;
3868 int count = 0;
3869
3870 SHRINKif ((ctxt->progressive == 0) && (ctxt->input->
cur - ctxt->input->base > 2 * 250) && (ctxt->
input->end - ctxt->input->cur < 2 * 250)) xmlSHRINK
(ctxt);
;
3871 if (RAW(*ctxt->input->cur) == '"') {
3872 NEXTxmlNextChar(ctxt);
3873 stop = '"';
3874 } else if (RAW(*ctxt->input->cur) == '\'') {
3875 NEXTxmlNextChar(ctxt);
3876 stop = '\'';
3877 } else {
3878 xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL((void*)0));
3879 return(NULL((void*)0));
3880 }
3881
3882 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3883 if (buf == NULL((void*)0)) {
3884 xmlErrMemory(ctxt, NULL((void*)0));
3885 return(NULL((void*)0));
3886 }
3887 ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
3888 cur = CUR_CHAR(l)xmlCurrentChar(ctxt, &l);
3889 while ((IS_CHAR(cur)(((cur) < 0x100) ? (((0x9 <= ((cur))) && (((cur
)) <= 0xa)) || (((cur)) == 0xd) || (0x20 <= ((cur)))) :
(((0x100 <= (cur)) && ((cur) <= 0xd7ff)) || ((
0xe000 <= (cur)) && ((cur) <= 0xfffd)) || ((0x10000
<= (cur)) && ((cur) <= 0x10ffff))))
) && (cur != stop)) { /* checked */
3890 if (len + 5 >= size) {
3891 xmlChar *tmp;