diff --git a/ChangeLog b/ChangeLog index f3ec0f51..76a5dd71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +Sun Dec 12 13:08:15 CET 1999 Daniel Veillard + + * configure.in, doc/xml.html : bumped to 1.8.0 + * xlink.[ch], Makefile.am : added framework for link detection + * parser.h: added nbChars to parser context, needed for cleanup. + * xmlmemory.c: removed a nasty bug when out of mem + * valid.[ch]: adding namespace support for attribute decl + * tester.c: added --debugent option + * debugXML.[ch]: added xmlDebugDumpEntities() + * parser.c: cleanup, avoiding use of CUR_PTR like plague, using + buffers instead, this was really needed, validation was breaking + in strange ways due to that. Added xmlParseStringPEReference() + and other parsing from strings functions. Entities processing + modified again, but PERef are still not handled correcly but + unless you're Eve Maller you won't notice :-) + * HTMLparser.c: large changes toward reliability, and switched to + lowercase internal tags, XHTML is lowercase, so it will help + that output is closer to next version. + * doc/* : regenerated the documentation, it is now hosted at + http://xmlsoft.org/ (same bits I just bought the domain :-) + + Fri Dec 3 13:46:32 CET 1999 Daniel Veillard * SAX.h, SAX.c, makefile.am: added SAX.h mostly useful for the diff --git a/Makefile.am b/Makefile.am index 54d62280..ed0b2bbc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,8 @@ libxml_la_SOURCES = \ xmlIO.c \ xmlmemory.c \ nanohttp.c \ - valid.c + valid.c \ + xlink.c xmlincdir = $(includedir)/gnome-xml xmlinc_HEADERS = \ @@ -46,7 +47,8 @@ xmlinc_HEADERS = \ xmlIO.h \ xmlmemory.h \ nanohttp.h \ - valid.h + valid.h \ + xlink.h DEPS = $(top_builddir)/libxml.la LDADDS = $(top_builddir)/libxml.la @Z_LIBS@ @M_LIBS@ diff --git a/SAX.h b/SAX.h index 8d9f3c73..0424fa78 100644 --- a/SAX.h +++ b/SAX.h @@ -10,6 +10,7 @@ #include #include #include "parser.h" +#include "xlink.h" #ifndef __XML_SAX_H__ #define __XML_SAX_H__ diff --git a/configure.in b/configure.in index 4b8c4c82..4c50f341 100644 --- a/configure.in +++ b/configure.in @@ -4,8 +4,8 @@ AC_INIT(entities.h) AM_CONFIG_HEADER(config.h) LIBXML_MAJOR_VERSION=1 -LIBXML_MINOR_VERSION=7 -LIBXML_MICRO_VERSION=4 +LIBXML_MINOR_VERSION=8 +LIBXML_MICRO_VERSION=0 LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION diff --git a/debugXML.c b/debugXML.c index ab799f74..650fc596 100644 --- a/debugXML.c +++ b/debugXML.c @@ -280,3 +280,136 @@ void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) { if (doc->root != NULL) xmlDebugDumpNodeList(output, doc->root, 1); } + +void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) { + int i; + xmlEntityPtr cur; + + if (output == NULL) output = stdout; + if (doc == NULL) { + fprintf(output, "DOCUMENT == NULL !\n"); + return; + } + + switch (doc->type) { + case XML_ELEMENT_NODE: + fprintf(output, "Error, ELEMENT found here "); + break; + case XML_ATTRIBUTE_NODE: + fprintf(output, "Error, ATTRIBUTE found here\n"); + break; + case XML_TEXT_NODE: + fprintf(output, "Error, TEXT\n"); + break; + case XML_CDATA_SECTION_NODE: + fprintf(output, "Error, CDATA_SECTION\n"); + break; + case XML_ENTITY_REF_NODE: + fprintf(output, "Error, ENTITY_REF\n"); + break; + case XML_ENTITY_NODE: + fprintf(output, "Error, ENTITY\n"); + break; + case XML_PI_NODE: + fprintf(output, "Error, PI\n"); + break; + case XML_COMMENT_NODE: + fprintf(output, "Error, COMMENT\n"); + break; + case XML_DOCUMENT_NODE: + fprintf(output, "DOCUMENT\n"); + break; + case XML_HTML_DOCUMENT_NODE: + fprintf(output, "HTML DOCUMENT\n"); + break; + case XML_DOCUMENT_TYPE_NODE: + fprintf(output, "Error, DOCUMENT_TYPE\n"); + break; + case XML_DOCUMENT_FRAG_NODE: + fprintf(output, "Error, DOCUMENT_FRAG\n"); + break; + case XML_NOTATION_NODE: + fprintf(output, "Error, NOTATION\n"); + break; + default: + fprintf(output, "NODE_%d\n", doc->type); + } + if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { + xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) + doc->intSubset->entities; + fprintf(output, "Entities in internal subset\n"); + for (i = 0;i < table->nb_entities;i++) { + cur = &table->table[i]; + fprintf(output, "%d : %s : ", i, cur->name); + switch (cur->type) { + case XML_INTERNAL_GENERAL_ENTITY: + fprintf(output, "INTERNAL GENERAL"); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + fprintf(output, "EXTERNAL PARSED"); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + fprintf(output, "EXTERNAL UNPARSED"); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + fprintf(output, "INTERNAL PARAMETER"); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + fprintf(output, "EXTERNAL PARAMETER"); + break; + default: + fprintf(output, "UNKNOWN TYPE %d", + cur->type); + } + if (cur->ExternalID != NULL) + fprintf(output, "ID \"%s\"", cur->ExternalID); + if (cur->SystemID != NULL) + fprintf(output, "SYSTEM \"%s\"", cur->SystemID); + if (cur->orig != NULL) + fprintf(output, "\n orig \"%s\"", cur->orig); + if (cur->content != NULL) + fprintf(output, "\n content \"%s\"", cur->content); + fprintf(output, "\n"); + } + } else + fprintf(output, "No entities in internal subset\n"); + if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { + xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) + doc->extSubset->entities; + fprintf(output, "Entities in external subset\n"); + for (i = 0;i < table->nb_entities;i++) { + cur = &table->table[i]; + fprintf(output, "%d : %s : ", i, cur->name); + switch (cur->type) { + case XML_INTERNAL_GENERAL_ENTITY: + fprintf(output, "INTERNAL GENERAL"); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + fprintf(output, "EXTERNAL PARSED"); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + fprintf(output, "EXTERNAL UNPARSED"); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + fprintf(output, "INTERNAL PARAMETER"); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + fprintf(output, "EXTERNAL PARAMETER"); + break; + default: + fprintf(output, "UNKNOWN TYPE %d", + cur->type); + } + if (cur->ExternalID != NULL) + fprintf(output, "ID \"%s\"", cur->ExternalID); + if (cur->SystemID != NULL) + fprintf(output, "SYSTEM \"%s\"", cur->SystemID); + if (cur->orig != NULL) + fprintf(output, "\n orig \"%s\"", cur->orig); + if (cur->content != NULL) + fprintf(output, "\n content \"%s\"", cur->content); + fprintf(output, "\n"); + } + } else + fprintf(output, "No entities in external subset\n"); +} diff --git a/debugXML.h b/debugXML.h index f73527ca..b24219ae 100644 --- a/debugXML.h +++ b/debugXML.h @@ -16,4 +16,5 @@ extern void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc); +extern void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc); #endif /* __DEBUG_XML__ */ diff --git a/doc/html/gnome-xml-entities.html b/doc/html/gnome-xml-entities.html index b0105df0..532fe281 100644 --- a/doc/html/gnome-xml-entities.html +++ b/doc/html/gnome-xml-entities.html @@ -115,7 +115,7 @@ SIZE="3" >

Name

Synopsis

Description

Details






















Name

Synopsis

Description

Details


















Name

Synopsis

Description

Details






Name

Synopsis

Description

Details







Name

Synopsis

Description

Details




























































the value parsed (as an int)the value parsed (as an int), 0 in case of error




























xmlChar *name); xmlChar* xmlGetNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *namespace); +xmlNodePtr xmlChar *lang); +xmlChar* xmlNodeGetBase (xmlDocPtr doc, + xmlNodePtr cur); int xmlRemoveProp

Description

Details




































Add a string range to an XML buffer.

Add a string range to an XML buffer. if len == -1, the lenght of +str is recomputed.



























































Search and get the value of an attribute associated to a node -This does the entity substitution.

FIXED or +default declaration values unless DTD use has been turned off.


xmlGetNsProp ()

xmlChar*    xmlGetNsProp                    (xmlNodePtr node,
+                                             const xmlChar *name,
+                                             const xmlChar *namespace);

Search and get the value of an attribute associated to a node +This attribute has to be anchored in the namespace specified. +This does the entity substitution. +This function looks in DTD attribute declaration for FIXED or +default declaration values unless DTD use has been turned off.

node : the node
name : the attribute name
namespace : the URI of the namespace
Returns :the attribute value or NULL if not found. +It's up to the caller to free the memory.












xmlNodeGetBase ()

xmlChar*    xmlNodeGetBase                  (xmlDocPtr doc,
+                                             xmlNodePtr cur);

Searches for the BASE URL. The code should work on both XML +and HTML document even if base mechanisms are completely different.

doc : the document the node pertains to
cur : the node being checked
Returns :a pointer to the base URL, or NULL if not found +It's up to the caller to free the memory.













Name

Synopsis

Description

Details

























































Name

Synopsis

Description

Details







Name

Synopsis

Description

Details















Name

Synopsis

Description

Details















+ @@ -226,6 +227,7 @@ + @@ -495,6 +497,7 @@ + diff --git a/doc/xml.html b/doc/xml.html index bfdaa990..e0e286fc 100644 Binary files a/doc/xml.html and b/doc/xml.html differ diff --git a/include/libxml/SAX.h b/include/libxml/SAX.h index 8d9f3c73..0424fa78 100644 --- a/include/libxml/SAX.h +++ b/include/libxml/SAX.h @@ -10,6 +10,7 @@ #include #include #include "parser.h" +#include "xlink.h" #ifndef __XML_SAX_H__ #define __XML_SAX_H__ diff --git a/include/libxml/debugXML.h b/include/libxml/debugXML.h index f73527ca..b24219ae 100644 --- a/include/libxml/debugXML.h +++ b/include/libxml/debugXML.h @@ -16,4 +16,5 @@ extern void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth); extern void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc); +extern void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc); #endif /* __DEBUG_XML__ */ diff --git a/include/libxml/tree.h b/include/libxml/tree.h index 20a64dfa..e046073a 100644 --- a/include/libxml/tree.h +++ b/include/libxml/tree.h @@ -112,6 +112,7 @@ typedef struct xmlAttribute { xmlAttributeDefault def; /* the default */ const xmlChar *defaultValue;/* or the default value */ xmlEnumerationPtr tree; /* or the enumeration tree if any */ + const xmlChar *prefix; /* the namespace prefix if any */ } xmlAttribute; typedef xmlAttribute *xmlAttributePtr; @@ -462,6 +463,9 @@ xmlAttrPtr xmlSetProp (xmlNodePtr node, const xmlChar *value); xmlChar * xmlGetProp (xmlNodePtr node, const xmlChar *name); +xmlChar * xmlGetNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *namespace); xmlNodePtr xmlStringGetNodeList (xmlDocPtr doc, const xmlChar *value); xmlNodePtr xmlStringLenGetNodeList (xmlDocPtr doc, @@ -484,6 +488,8 @@ xmlChar * xmlNodeGetContent (xmlNodePtr cur); xmlChar * xmlNodeGetLang (xmlNodePtr cur); void xmlNodeSetLang (xmlNodePtr cur, const xmlChar *lang); +xmlChar * xmlNodeGetBase (xmlDocPtr doc, + xmlNodePtr cur); /* * Removing content. diff --git a/include/libxml/xlink.h b/include/libxml/xlink.h new file mode 100644 index 00000000..7d1025f1 --- /dev/null +++ b/include/libxml/xlink.h @@ -0,0 +1,175 @@ +/* + * xlink.h : interfaces to the hyperlinks detection module + * + * See Copyright for the status of this software. + * + * Related specification: http://www.w3.org/TR/xlink + * http://www.w3.org/HTML/ + * and XBase + * + * Daniel.Veillard@w3.org + */ + +#ifndef __XML_XLINK_H__ +#define __XML_XLINK_H__ + +#include "tree.h" + +/** + * Various defines for the various Link properties. + * + * NOTE: the link detection layer will try to resolve QName expansion + * of namespaces, if "foo" is the prefix for "http://foo.com/" + * then the link detection layer will expand role="foo:myrole" + * to "http://foo.com/:myrole" + * NOTE: the link detection layer will expand URI-Refences found on + * href attributes by using the base mechanism if found. + */ +typedef xmlChar *xlinkHRef; +typedef xmlChar *xlinkRole; +typedef xmlChar *xlinkTitle; + +typedef enum { + XLINK_TYPE_NONE = 0, + XLINK_TYPE_SIMPLE, + XLINK_TYPE_EXTENDED, + XLINK_TYPE_EXTENDED_SET +} xlinkType; + +typedef enum { + XLINK_SHOW_NONE = 0, + XLINK_SHOW_NEW, + XLINK_SHOW_EMBED, + XLINK_SHOW_REPLACE +} xlinkShow; + +typedef enum { + XLINK_ACTUATE_NONE = 0, + XLINK_ACTUATE_AUTO, + XLINK_ACTUATE_ONREQUEST +} xlinkActuate; + +/** + * xlinkNodeDetectFunc: + * @ctx: user data pointer + * @node: the node to check + * + * This is the prototype for the link detection routine + * It calls the default link detection callbacks upon link detection. + */ +typedef void +(*xlinkNodeDetectFunc) (void *ctx, + xmlNodePtr node); + +/** + * The link detection module interract with the upper layers using + * a set of callback registered at parsing time. + */ + +/** + * xlinkSimpleLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @href: the target of the link + * @role: the role string + * @title: the link title + * + * This is the prototype for a simple link detection callback. + */ +typedef void +(*xlinkSimpleLinkFunk) (void *ctx, + xmlNodePtr node, + const xlinkHRef href, + const xlinkRole role, + const xlinkTitle title); + +/** + * xlinkExtendedLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbArcs: the number of arcs detected on the link + * @from: pointer to the array of source roles found on the arcs + * @to: pointer to the array of target roles found on the arcs + * @show: array of values for the show attributes found on the arcs + * @actuate: array of values for the actuate attributes found on the arcs + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link detection callback. + */ +typedef void +(*xlinkExtendedLinkFunk)(void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbArcs, + const xlinkRole *from, + const xlinkRole *to, + xlinkShow *show, + xlinkActuate *actuate, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * xlinkExtendedLinkSetFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link set detection callback. + */ +typedef void +(*xlinkExtendedLinkSetFunk) (void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * This is the structure containing a set of Links detection callbacks + * + * There is no default xlink callbacks, if one want to get link + * recognition activated, those call backs must be provided before parsing. + */ +typedef struct xlinkHandler { + xlinkSimpleLinkFunk simple; + xlinkExtendedLinkFunk extended; + xlinkExtendedLinkSetFunk set; +} xlinkHandler; +typedef xlinkHandler *xlinkHandlerPtr; + +/** + * the default detection routine, can be overriden, they call the default + * detection callbacks. + */ + +xlinkNodeDetectFunc xlinkGetDefaultDetect (void); +void xlinkSetDefaultDetect (xlinkNodeDetectFunc func); + +/** + * Routines to set/get the default handlers. + */ +xlinkHandlerPtr xlinkGetDefaultHandler (void); +void xlinkSetDefaultHandler (xlinkHandlerPtr handler); + +/* + * Link detection module itself. + */ +xlinkType xlinkIsLink (xmlDocPtr doc, + xmlNodePtr node); + +#endif /* __XML_XLINK_H__ */ diff --git a/parser.c b/parser.c index e543c383..eef47211 100644 --- a/parser.c +++ b/parser.c @@ -164,6 +164,13 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { return(0); } ret = xmlParserInputBufferGrow(in->buf, len); + + /* + * NOTE : in->base may be a "dandling" i.e. freed pointer in this + * block, but we use it really as an integer to do some + * pointer arithmetic. Insure will raise it as a bug but in + * that specific case, that's not ! + */ if (in->base != in->buf->buffer->content) { /* * the buffer has been realloced @@ -235,6 +242,8 @@ xmlParserInputShrink(xmlParserInputPtr in) { int xmlSubstituteEntitiesDefaultValue = 0; int xmlDoValidityCheckingDefaultValue = 0; +xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, + const xmlChar ** str); /* * Generic function for accessing stacks in the Parser Context @@ -298,7 +307,7 @@ PUSH_AND_POP(xmlNodePtr, node) */ #define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur)) -#define SKIP(val) ctxt->input->cur += (val) +#define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val) #define NXT(val) ctxt->input->cur[(val)] #define CUR_PTR ctxt->input->cur #define SHRINK xmlParserInputShrink(ctxt->input); \ @@ -330,6 +339,7 @@ PUSH_AND_POP(xmlNodePtr, node) ctxt->input->line++; ctxt->input->col = 1; \ } else ctxt->input->col++; \ ctxt->input->cur++; \ + ctxt->nbChars++; \ if (*ctxt->input->cur == 0) \ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \ } \ @@ -646,6 +656,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt) ctxt->vctxt.warning = xmlParserValidityWarning; ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue; ctxt->record_info = 0; + ctxt->nbChars = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); } @@ -723,6 +734,8 @@ xmlClearParserCtxt(xmlParserCtxtPtr ctxt) void xmlParserHandleReference(xmlParserCtxtPtr ctxt); void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt); +xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt, + const xmlChar **str); /** * xmlParseCharRef: @@ -737,7 +750,7 @@ void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt); * Characters referred to using character references must match the * production for Char. * - * Returns the value parsed (as an int) + * Returns the value parsed (as an int), 0 in case of error */ int xmlParseCharRef(xmlParserCtxtPtr ctxt) { @@ -815,6 +828,104 @@ fprintf(stderr, "xmlParseCharRef : ctxt->token != 0\n"); return(0); } +/** + * xmlParseStringCharRef: + * @ctxt: an XML parser context + * @str: a pointer to an index in the string + * + * parse Reference declarations, variant parsing from a string rather + * than an an input flow. + * + * [66] CharRef ::= '&#' [0-9]+ ';' | + * '&#x' [0-9a-fA-F]+ ';' + * + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + * + * Returns the value parsed (as an int), 0 in case of error, str will be + * updated to the current value of the index + */ +int +xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) { + const xmlChar *ptr; + xmlChar cur; + int val = 0; + + if ((str == NULL) || (*str == NULL)) return(0); + ptr = *str; + cur = *ptr; + if ((cur = '&') && (ptr[1] == '#') && (ptr[2] == 'x')) { + ptr += 3; + cur = *ptr; + while (cur != ';') { + if ((cur >= '0') && (cur <= '9')) + val = val * 16 + (cur - '0'); + else if ((cur >= 'a') && (cur <= 'f')) + val = val * 16 + (cur - 'a') + 10; + else if ((cur >= 'A') && (cur <= 'F')) + val = val * 16 + (cur - 'A') + 10; + else { + ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "xmlParseCharRef: invalid hexadecimal value\n"); + ctxt->wellFormed = 0; + val = 0; + break; + } + ptr++; + cur = *ptr; + } + if (cur == ';') + ptr++; + } else if ((cur = '&') && (ptr[1] == '#')){ + ptr += 2; + cur = *ptr; + while (cur != ';') { + if ((cur >= '0') && (cur <= '9')) + val = val * 10 + (cur - '0'); + else { + ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "xmlParseCharRef: invalid decimal value\n"); + ctxt->wellFormed = 0; + val = 0; + break; + } + ptr++; + cur = *ptr; + } + if (cur == ';') + ptr++; + } else { + ctxt->errNo = XML_ERR_INVALID_CHARREF; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "xmlParseCharRef: invalid value\n"); + ctxt->wellFormed = 0; + return(0); + } + *str = ptr; + + /* + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + */ + if (IS_CHAR(val)) { + return(val); + } else { + ctxt->errNo = XML_ERR_INVALID_CHAR; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "CharRef: invalid xmlChar value %d\n", val); + ctxt->wellFormed = 0; + } + return(0); +} + /** * xmlParserHandleReference: * @ctxt: the parser context @@ -1323,6 +1434,116 @@ xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what, return(buffer); } +/** + * xmlStringDecodeEntities: + * @ctxt: the parser context + * @str: the input string + * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF + * @end: an end marker xmlChar, 0 if none + * @end2: an end marker xmlChar, 0 if none + * @end3: an end marker xmlChar, 0 if none + * + * [67] Reference ::= EntityRef | CharRef + * + * [69] PEReference ::= '%' Name ';' + * + * Returns A newly allocated string with the substitution done. The caller + * must deallocate it ! + */ +xmlChar * +xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, + xmlChar end, xmlChar end2, xmlChar end3) { + xmlChar *buffer = NULL; + int buffer_size = 0; + xmlChar *out = NULL; + + xmlChar *current = NULL; + xmlEntityPtr ent; + xmlChar cur; + + /* + * allocate a translation buffer. + */ + buffer_size = 500; + buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) { + perror("xmlDecodeEntities: malloc failed"); + return(NULL); + } + out = buffer; + + /* + * Ok loop until we reach one of the ending char or a size limit. + */ + cur = *str; + while ((cur != 0) && (cur != end) && + (cur != end2) && (cur != end3)) { + + if (cur == 0) break; + if ((cur == '&') && (str[1] == '#')) { + int val = xmlParseStringCharRef(ctxt, &str); + if (val != 0) + *out++ = val; + } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) { + ent = xmlParseStringEntityRef(ctxt, &str); + if ((ent != NULL) && + (ctxt->replaceEntities != 0)) { + current = ent->content; + while (*current != 0) { + *out++ = *current++; + if (out - buffer > buffer_size - 100) { + int index = out - buffer; + + growBuffer(buffer); + out = &buffer[index]; + } + } + } else if (ent != NULL) { + int i = xmlStrlen(ent->name); + const xmlChar *cur = ent->name; + + *out++ = '&'; + if (out - buffer > buffer_size - i - 100) { + int index = out - buffer; + + growBuffer(buffer); + out = &buffer[index]; + } + for (;i > 0;i--) + *out++ = *cur++; + *out++ = ';'; + } + } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) { + ent = xmlParseStringPEReference(ctxt, &str); + if (ent != NULL) { + current = ent->content; + while (*current != 0) { + *out++ = *current++; + if (out - buffer > buffer_size - 100) { + int index = out - buffer; + + growBuffer(buffer); + out = &buffer[index]; + } + } + } + } else { + /* invalid for UTF-8 , use COPY(out); !!!!!! */ + *out++ = cur; + if (out - buffer > buffer_size - 100) { + int index = out - buffer; + + growBuffer(buffer); + out = &buffer[index]; + } + str++; + } + cur = *str; + } + *out = 0; + return(buffer); +} + /************************************************************************ * * @@ -1494,8 +1715,10 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) */ xmlChar * xmlStrndup(const xmlChar *cur, int len) { - xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar)); - + xmlChar *ret; + + if ((cur == NULL) || (len < 0)) return(NULL); + ret = xmlMalloc((len + 1) * sizeof(xmlChar)); if (ret == NULL) { fprintf(stderr, "malloc of %ld byte failed\n", (len + 1) * (long)sizeof(xmlChar)); @@ -1518,6 +1741,7 @@ xmlChar * xmlStrdup(const xmlChar *cur) { const xmlChar *p = cur; + if (cur == NULL) return(NULL); while (IS_CHAR(*p)) p++; return(xmlStrndup(cur, p - cur)); } @@ -1535,8 +1759,10 @@ xmlStrdup(const xmlChar *cur) { xmlChar * xmlCharStrndup(const char *cur, int len) { int i; - xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar)); - + xmlChar *ret; + + if ((cur == NULL) || (len < 0)) return(NULL); + ret = xmlMalloc((len + 1) * sizeof(xmlChar)); if (ret == NULL) { fprintf(stderr, "malloc of %ld byte failed\n", (len + 1) * (long)sizeof(xmlChar)); @@ -1562,6 +1788,7 @@ xmlChar * xmlCharStrdup(const char *cur) { const char *p = cur; + if (cur == NULL) return(NULL); while (*p != '\0') p++; return(xmlCharStrndup(cur, p - cur)); } @@ -1580,6 +1807,9 @@ int xmlStrcmp(const xmlChar *str1, const xmlChar *str2) { register int tmp; + if ((str1 == NULL) && (str2 == NULL)) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); do { tmp = *str1++ - *str2++; if (tmp != 0) return(tmp); @@ -1603,6 +1833,9 @@ xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) { register int tmp; if (len <= 0) return(0); + if ((str1 == NULL) && (str2 == NULL)) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); do { tmp = *str1++ - *str2++; if (tmp != 0) return(tmp); @@ -1624,6 +1857,7 @@ xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) { const xmlChar * xmlStrchr(const xmlChar *str, xmlChar val) { + if (str == NULL) return(NULL); while (*str != 0) { if (*str == val) return((xmlChar *) str); str++; @@ -2041,37 +2275,68 @@ xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) { */ xmlChar * xmlParseQuotedString(xmlParserCtxtPtr ctxt) { - xmlChar *ret = NULL; - const xmlChar *q; + xmlChar *buf = NULL; + int len = 0; + int size = 100; + xmlChar c; + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", size); + return(NULL); + } if (CUR == '"') { NEXT; - q = CUR_PTR; - while (IS_CHAR(CUR) && (CUR != '"')) NEXT; - if (CUR != '"') { + c = CUR; + while (IS_CHAR(c) && (c != '"')) { + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = c; + NEXT; + c = CUR; + } + if (c != '"') { ctxt->errNo = XML_ERR_STRING_NOT_CLOSED; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q); + ctxt->sax->error(ctxt->userData, + "String not closed \"%.50s\"\n", buf); ctxt->wellFormed = 0; } else { - ret = xmlStrndup(q, CUR_PTR - q); NEXT; } } else if (CUR == '\''){ NEXT; - q = CUR_PTR; - while (IS_CHAR(CUR) && (CUR != '\'')) NEXT; + c = CUR; + while (IS_CHAR(c) && (c != '\'')) { + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = c; + NEXT; + c = CUR; + } if (CUR != '\'') { ctxt->errNo = XML_ERR_STRING_NOT_CLOSED; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q); + ctxt->sax->error(ctxt->userData, + "String not closed \"%.50s\"\n", buf); ctxt->wellFormed = 0; } else { - ret = xmlStrndup(q, CUR_PTR - q); NEXT; } } - return(ret); + return(buf); } /** @@ -2293,6 +2558,51 @@ xmlParseName(xmlParserCtxtPtr ctxt) { return(xmlStrndup(buf, len)); } +/** + * xmlParseStringName: + * @ctxt: an XML parser context + * @str: a pointer to an index in the string + * + * parse an XML name. + * + * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + * CombiningChar | Extender + * + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + * + * [6] Names ::= Name (S Name)* + * + * Returns the Name parsed or NULL. The str pointer + * is updated to the current location in the string. + */ + +xmlChar * +xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + const xmlChar *ptr; + const xmlChar *start; + xmlChar cur; + + if ((str == NULL) || (*str == NULL)) return(NULL); + + start = ptr = *str; + cur = *ptr; + if (!IS_LETTER(cur) && (cur != '_') && + (cur != ':')) { + return(NULL); + } + + while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) || + (cur == '.') || (cur == '-') || + (cur == '_') || (cur == ':') || + (IS_COMBINING(cur)) || + (IS_EXTENDER(cur))) { + ptr++; + cur = *ptr; + } + *str = ptr; + return(xmlStrndup(start, ptr - start )); +} + /** * xmlParseNmtoken: * @ctxt: an XML parser context @@ -2349,138 +2659,93 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { xmlChar * xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + xmlChar *buf = NULL; + int len = 0; + int size = 100; + xmlChar c; + xmlChar stop; xmlChar *ret = NULL; - const xmlChar *org = NULL; - const xmlChar *tst = NULL; - const xmlChar *temp = NULL; xmlParserInputPtr input; - SHRINK; - if (CUR == '"') { - ctxt->instate = XML_PARSER_ENTITY_VALUE; - input = ctxt->input; - NEXT; - org = CUR_PTR; - /* - * NOTE: 4.4.5 Included in Literal - * When a parameter entity reference appears in a literal entity - * value, ... a single or double quote character in the replacement - * text is always treated as a normal data character and will not - * terminate the literal. - * In practice it means we stop the loop only when back at parsing - * the initial entity and the quote is found - */ - while ((CUR != '"') || (ctxt->input != input)) { - tst = CUR_PTR; - /* - * NOTE: 4.4.7 Bypassed - * When a general entity reference appears in the EntityValue in - * an entity declaration, it is bypassed and left as is. - * so XML_SUBSTITUTE_REF is not set. - */ - if (ctxt->input != input) - temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF, - 0, 0, 0); - else - temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF, - '"', 0, 0); - - /* - * Pop-up of finished entities. - */ - while ((CUR == 0) && (ctxt->inputNr > 1)) - xmlPopInput(ctxt); - - if ((temp == NULL) && (tst == CUR_PTR)) { - ret = xmlStrndup((xmlChar *) "", 0); - break; - } - if ((temp[0] == 0) && (tst == CUR_PTR)) { - xmlFree((char *)temp); - ret = xmlStrndup((xmlChar *) "", 0); - break; - } - ret = xmlStrcat(ret, temp); - if (temp != NULL) xmlFree((char *)temp); - GROW; - } - if (CUR != '"') { - ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED; - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n"); - ctxt->wellFormed = 0; - } else { - if (orig != NULL) /* !!!!!!!!! */ - *orig = xmlStrndup(org, CUR_PTR - org); - if (ret == NULL) - ret = xmlStrndup((xmlChar *) "", 0); - NEXT; - } - } else if (CUR == '\'') { - ctxt->instate = XML_PARSER_ENTITY_VALUE; - input = ctxt->input; - NEXT; - org = CUR_PTR; - /* - * NOTE: 4.4.5 Included in Literal - * When a parameter entity reference appears in a literal entity - * value, ... a single or double quote character in the replacement - * text is always treated as a normal data character and will not - * terminate the literal. - * In practice it means we stop the loop only when back at parsing - * the initial entity and the quote is found - */ - while ((CUR != '\'') || (ctxt->input != input)) { - tst = CUR_PTR; - /* - * NOTE: 4.4.7 Bypassed - * When a general entity reference appears in the EntityValue in - * an entity declaration, it is bypassed and left as is. - * so XML_SUBSTITUTE_REF is not set. - */ - if (ctxt->input != input) - temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF, - 0, 0, 0); - else - temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF, - '\'', 0, 0); - - /* - * Pop-up of finished entities. - */ - while ((CUR == 0) && (ctxt->inputNr > 1)) - xmlPopInput(ctxt); - - if ((temp == NULL) && (tst == CUR_PTR)) { - ret = xmlStrndup((xmlChar *) "", 0); - break; - } - if ((temp[0] == 0) && (tst == CUR_PTR)) { - xmlFree((char *)temp); - ret = xmlStrndup((xmlChar *) "", 0); - break; - } - ret = xmlStrcat(ret, temp); - if (temp != NULL) xmlFree((char *)temp); - GROW; - } - if (CUR != '\'') { - ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED; - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "EntityValue: ' expected\n"); - ctxt->wellFormed = 0; - } else { - if (orig != NULL) /* !!!!!!!!! */ - *orig = xmlStrndup(org, CUR_PTR - org); - if (ret == NULL) - ret = xmlStrndup((xmlChar *) "", 0); - NEXT; - } - } else { + if (CUR == '"') stop = '"'; + else if (CUR == '\'') stop = '\''; + else { ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n"); ctxt->wellFormed = 0; + return(NULL); + } + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", size); + return(NULL); + } + + /* + * The content of the entity definition is copied in a buffer. + */ + + ctxt->instate = XML_PARSER_ENTITY_VALUE; + input = ctxt->input; + GROW; + NEXT; + c = CUR; + /* + * NOTE: 4.4.5 Included in Literal + * When a parameter entity reference appears in a literal entity + * value, ... a single or double quote character in the replacement + * text is always treated as a normal data character and will not + * terminate the literal. + * In practice it means we stop the loop only when back at parsing + * the initial entity and the quote is found + */ + while (IS_CHAR(c) && ((c != stop) || (ctxt->input != input))) { + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = c; + NEXT; + /* + * Pop-up of finished entities. + */ + while ((CUR == 0) && (ctxt->inputNr > 1)) + xmlPopInput(ctxt); + c = CUR; + if (c == 0) { + GROW; + c = CUR; + } + } + buf[len] = 0; + + /* + * Then PEReference entities are substituted. + */ + if (c != stop) { + ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n"); + ctxt->wellFormed = 0; + } else { + NEXT; + /* + * NOTE: 4.4.7 Bypassed + * When a general entity reference appears in the EntityValue in + * an entity declaration, it is bypassed and left as is. + * so XML_SUBSTITUTE_REF is not set. + */ + ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF, + 0, 0, 0); + if (orig != NULL) + *orig = buf; + else + xmlFree(buf); } return(ret); @@ -2651,47 +2916,62 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) { xmlChar * xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { - const xmlChar *q; - xmlChar *ret = NULL; + xmlChar *buf = NULL; + int len = 0; + int size = 100; + xmlChar cur; + xmlChar stop; SHRINK; if (CUR == '"') { NEXT; - q = CUR_PTR; - while ((IS_CHAR(CUR)) && (CUR != '"')) - NEXT; - if (!IS_CHAR(CUR)) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n"); - ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; - ctxt->wellFormed = 0; - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + stop = '"'; } else if (CUR == '\'') { NEXT; - q = CUR_PTR; - while ((IS_CHAR(CUR)) && (CUR != '\'')) - NEXT; - if (!IS_CHAR(CUR)) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n"); - ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; - ctxt->wellFormed = 0; - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + stop = '\''; } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "SystemLiteral \" or ' expected\n"); ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED; ctxt->wellFormed = 0; + return(NULL); } - return(ret); + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", size); + return(NULL); + } + cur = CUR; + while ((IS_CHAR(cur)) && (cur != stop)) { + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = cur; + NEXT; + cur = CUR; + if (cur == 0) { + GROW; + SHRINK; + cur = CUR; + } + } + buf[len] = 0; + if (!IS_CHAR(cur)) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n"); + ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; + ctxt->wellFormed = 0; + } else { + NEXT; + } + return(buf); } /** @@ -2707,45 +2987,61 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { xmlChar * xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { - const xmlChar *q; - xmlChar *ret = NULL; + xmlChar *buf = NULL; + int len = 0; + int size = 100; + xmlChar cur; + xmlChar stop; SHRINK; if (CUR == '"') { NEXT; - q = CUR_PTR; - while (IS_PUBIDCHAR(CUR)) NEXT; - if (CUR != '"') { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n"); - ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; - ctxt->wellFormed = 0; - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + stop = '"'; } else if (CUR == '\'') { NEXT; - q = CUR_PTR; - while (IS_PUBIDCHAR(CUR)) NEXT; - if (CUR != '\'') { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n"); - ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; - ctxt->wellFormed = 0; - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + stop = '\''; } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "SystemLiteral \" or ' expected\n"); ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED; ctxt->wellFormed = 0; + return(NULL); } - - return(ret); + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", size); + return(NULL); + } + cur = CUR; + while ((IS_PUBIDCHAR(cur)) && (cur != stop)) { + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = cur; + NEXT; + cur = CUR; + if (cur == 0) { + GROW; + SHRINK; + cur = CUR; + } + } + buf[len] = 0; + if (cur != stop) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n"); + ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED; + ctxt->wellFormed = 0; + } else { + NEXT; + } + return(buf); } /** @@ -2905,7 +3201,10 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) { * "S SystemLiteral" is not detected. From a purely parsing * point of view that's a nice mess. */ - const xmlChar *ptr = CUR_PTR; + const xmlChar *ptr; + GROW; + + ptr = CUR_PTR; if (!IS_BLANK(*ptr)) return(NULL); while (IS_BLANK(*ptr)) ptr++; @@ -2936,9 +3235,12 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) { */ void xmlParseComment(xmlParserCtxtPtr ctxt) { - const xmlChar *q, *start; - const xmlChar *r; - xmlChar *val; + xmlChar *buf = NULL; + int len = 0; + int size = 100; + xmlChar q; + xmlChar r; + xmlChar cur; /* * Check that there is a comment right here. @@ -2949,34 +3251,57 @@ xmlParseComment(xmlParserCtxtPtr ctxt) { ctxt->instate = XML_PARSER_COMMENT; SHRINK; SKIP(4); - start = q = CUR_PTR; + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "malloc of %d byte failed\n", size); + return; + } + q = CUR; NEXT; - r = CUR_PTR; + r = CUR; NEXT; - while (IS_CHAR(CUR) && - ((CUR == ':') || (CUR != '>') || - (*r != '-') || (*q != '-'))) { - if ((*r == '-') && (*q == '-')) { + cur = CUR; + while (IS_CHAR(cur) && + ((cur != '>') || + (r != '-') || (q != '-'))) { + if ((r == '-') && (q == '-')) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "Comment must not contain '--' (double-hyphen)`\n"); ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT; ctxt->wellFormed = 0; } - NEXT;r++;q++; + if (len + 1 >= size) { + size *= 2; + buf = xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + fprintf(stderr, "realloc of %d byte failed\n", size); + return; + } + } + buf[len++] = q; + q = r; + r = cur; + NEXT; + cur = CUR; + if (cur == 0) { + SHRINK; + GROW; + cur = CUR; + } } - if (!IS_CHAR(CUR)) { + buf[len] = 0; + if (!IS_CHAR(cur)) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, - "Comment not terminated \n