* gnulib-local/lib/libxml/*: Update from libxml2 2.9.9.
* gnulib-local/m4/libxml.m4 (gl_LIBXML): Don't test for _stat.
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
htmlParseErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, int val)
{
#define UPP(val) (toupper(ctxt->input->cur[(val)]))
#define CUR_PTR ctxt->input->cur
+#define BASE_PTR ctxt->input->base
#define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
(ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
"menu", "p", "head", "ul", NULL,
"p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
"div", "p", "head", NULL,
-"noscript", "p", NULL,
+"noscript", "script", NULL,
"center", "font", "b", "i", "p", "head", NULL,
"a", "a", "head", NULL,
"caption", "p", NULL,
(*in == '_') || (*in == '-') ||
(*in == ':') || (*in == '.'))
in++;
+
+ if (in == ctxt->input->end)
+ return(NULL);
+
if ((*in > 0) && (*in < 0x80)) {
count = in - ctxt->input->cur;
ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
int len = 0, l;
int c;
int count = 0;
+ const xmlChar *base = ctxt->input->base;
/*
* Handler for more complex cases
len += l;
NEXTL(l);
c = CUR_CHAR(l);
+ if (ctxt->input->base != base) {
+ /*
+ * We changed encoding from an unknown encoding
+ * Input buffer changed location, so we better start again
+ */
+ return(htmlParseNameComplex(ctxt));
+ }
}
+
+ if (ctxt->input->cur - ctxt->input->base < len) {
+ /* Sanity check */
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "unexpected change of input buffer", NULL, NULL);
+ return (NULL);
+ }
+
return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
}
static xmlChar *
htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
- const xmlChar *q;
+ size_t len = 0, startPosition = 0;
xmlChar *ret = NULL;
if (CUR == '"') {
NEXT;
- q = CUR_PTR;
- while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
+
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
+
+ while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
NEXT;
+ len++;
+ }
if (!IS_CHAR_CH(CUR)) {
htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
"Unfinished SystemLiteral\n", NULL, NULL);
} else {
- ret = xmlStrndup(q, CUR_PTR - q);
+ ret = xmlStrndup((BASE_PTR+startPosition), len);
NEXT;
}
} else if (CUR == '\'') {
NEXT;
- q = CUR_PTR;
- while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
+
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
+
+ while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
NEXT;
+ len++;
+ }
if (!IS_CHAR_CH(CUR)) {
htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
"Unfinished SystemLiteral\n", NULL, NULL);
} else {
- ret = xmlStrndup(q, CUR_PTR - q);
+ ret = xmlStrndup((BASE_PTR+startPosition), len);
NEXT;
}
} else {
static xmlChar *
htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
- const xmlChar *q;
+ size_t len = 0, startPosition = 0;
xmlChar *ret = NULL;
/*
* Name ::= (Letter | '_') (NameChar)*
*/
if (CUR == '"') {
NEXT;
- q = CUR_PTR;
- while (IS_PUBIDCHAR_CH(CUR)) NEXT;
+
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
+
+ while (IS_PUBIDCHAR_CH(CUR)) {
+ len++;
+ NEXT;
+ }
+
if (CUR != '"') {
htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
"Unfinished PubidLiteral\n", NULL, NULL);
} else {
- ret = xmlStrndup(q, CUR_PTR - q);
+ ret = xmlStrndup((BASE_PTR + startPosition), len);
NEXT;
}
} else if (CUR == '\'') {
NEXT;
- q = CUR_PTR;
- while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\''))
- NEXT;
+
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
+
+ while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
+ len++;
+ NEXT;
+ }
+
if (CUR != '\'') {
htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
"Unfinished PubidLiteral\n", NULL, NULL);
} else {
- ret = xmlStrndup(q, CUR_PTR - q);
+ ret = xmlStrndup((BASE_PTR + startPosition), len);
NEXT;
}
} else {
processed = ctxt->input->cur - ctxt->input->base;
xmlBufShrink(ctxt->input->buf->buffer, processed);
nbchars = xmlCharEncInput(ctxt->input->buf, 1);
+ xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
if (nbchars < 0) {
htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
"htmlCheckEncoding: encoder error\n",
NULL, NULL);
}
- xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
}
}
}
htmlParseElementInternal(htmlParserCtxtPtr ctxt) {
const xmlChar *name;
const htmlElemDesc * info;
- htmlParserNodeInfo node_info = { 0, };
+ htmlParserNodeInfo node_info = { NULL, 0, 0, 0, 0 };
int failed;
if ((ctxt == NULL) || (ctxt->input == NULL)) {
ctxt->wellFormed = 1;
ctxt->replaceEntities = 0;
ctxt->linenumbers = xmlLineNumbersDefaultValue;
+ ctxt->keepBlanks = xmlKeepBlanksDefaultValue;
ctxt->html = 1;
ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_0;
ctxt->vctxt.userData = ctxt;
*/
htmlDocPtr
-htmlSAXParseDoc(xmlChar *cur, const char *encoding, htmlSAXHandlerPtr sax, void *userData) {
+htmlSAXParseDoc(const xmlChar *cur, const char *encoding,
+ htmlSAXHandlerPtr sax, void *userData) {
htmlDocPtr ret;
htmlParserCtxtPtr ctxt;
*/
htmlDocPtr
-htmlParseDoc(xmlChar *cur, const char *encoding) {
+htmlParseDoc(const xmlChar *cur, const char *encoding) {
return(htmlSAXParseDoc(cur, encoding, NULL, NULL));
}
* DICT_FREE:
* @str: a string
*
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
* current scope
*/
#define DICT_FREE(str) \
xmlInitNodeInfoSeq(&ctxt->node_seq);
if (ctxt->attsDefault != NULL) {
- xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+ xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
ctxt->attsDefault = NULL;
}
if (ctxt->attsSpecial != NULL) {
XMLPUBFUN int XMLCALL
htmlParseDocument(htmlParserCtxtPtr ctxt);
XMLPUBFUN htmlDocPtr XMLCALL
- htmlSAXParseDoc (xmlChar *cur,
+ htmlSAXParseDoc (const xmlChar *cur,
const char *encoding,
htmlSAXHandlerPtr sax,
void *userData);
XMLPUBFUN htmlDocPtr XMLCALL
- htmlParseDoc (xmlChar *cur,
+ htmlParseDoc (const xmlChar *cur,
const char *encoding);
XMLPUBFUN htmlDocPtr XMLCALL
htmlSAXParseFile(const char *filename,
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
/*
* save the content to a temp buffer.
*/
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
- if (enc != cur->charset) {
- if (cur->charset != XML_CHAR_ENCODING_UTF8) {
- /*
- * Not supported yet
- */
- *mem = NULL;
- *size = 0;
- return;
- }
-
+ if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
- } else {
- handler = xmlFindCharEncodingHandler(encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
buf = xmlAllocOutputBufferInternal(handler);
if (buf == NULL) {
*mem = NULL;
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
- if (enc != cur->charset) {
- if (cur->charset != XML_CHAR_ENCODING_UTF8) {
- /*
- * Not supported yet
- */
- return(-1);
- }
-
+ if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
- } else {
- handler = xmlFindCharEncodingHandler(encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
buf = xmlOutputBufferCreateFile(f, handler);
if (buf == NULL) return(-1);
htmlDocContentDumpOutput(buf, cur, NULL);
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
- if (enc != cur->charset) {
- if (cur->charset != XML_CHAR_ENCODING_UTF8) {
- /*
- * Not supported yet
- */
- return(-1);
- }
-
+ if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
/*
* save the content to a temp buffer.
*/
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
- if (enc != cur->charset) {
- if (cur->charset != XML_CHAR_ENCODING_UTF8) {
- /*
- * Not supported yet
- */
- return(-1);
- }
-
+ if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
} else {
htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
- }
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+ }
/*
* save the content to a temp buffer.
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <stddef.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
* @ctxt: an XML validation parser context
* @msg: a string to accompany the error message
*/
-static void
+static void LIBXML_ATTR_FORMAT(2,0)
xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
xmlStructuredErrorFunc schannel = NULL;
const char *str1 = "out of memory\n";
*
* Handle a validation error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const char *str1, const char *str2)
{
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
*
* Handle a parser warning
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1)
{
*
* Handle a namespace error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
*
* Handle a namespace warning
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
if (name != NULL)
xmlFree(name);
+ if (nval != NULL)
+ xmlFree(nval);
return;
}
} else {
xmlFree(ns);
if (name != NULL)
xmlFree(name);
+ if (nval != NULL)
+ xmlFree(nval);
return;
}
} else {
name, namespace->href);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ if (name != NULL)
+ xmlFree(name);
goto error;
}
}
#ifdef DEBUG_SAX_TREE
xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
#endif
- nodePush(ctxt, ret);
+ if (nodePush(ctxt, ret) < 0) {
+ xmlUnlinkNode(ret);
+ xmlFreeNode(ret);
+ return;
+ }
/*
* Link the child element
else {
ret->line = 65535;
if (ctxt->options & XML_PARSE_BIG_LINES)
- ret->psvi = (void *) (long) ctxt->input->line;
+ ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
}
}
}
ctxt->freeElems = ret->next;
ctxt->freeElemsNr--;
memset(ret, 0, sizeof(xmlNode));
+ ret->doc = ctxt->myDoc;
ret->type = XML_ELEMENT_NODE;
if (ctxt->dictNames)
} else {
/*
* any out of memory error would already have been raised
- * but we can't be garanteed it's the actual error due to the
+ * but we can't be guaranteed it's the actual error due to the
* API, best is to skip in this case
*/
continue;
/*
* We are parsing a new node.
*/
- nodePush(ctxt, ret);
+ if (nodePush(ctxt, ret) < 0) {
+ xmlUnlinkNode(ret);
+ xmlFreeNode(ret);
+ return;
+ }
/*
* Link the child element
xmlTextConcat(lastChild, value, len);
} else {
ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
- xmlAddChild(ctxt->node, ret);
+ if (xmlAddChild(ctxt->node, ret) == NULL)
+ xmlFreeNode(ret);
}
}
size_t use; /* The buffer size used */
size_t size; /* The buffer size */
xmlBufferPtr buffer; /* wrapper for an old buffer */
- int error; /* an error code if a failure occured */
+ int error; /* an error code if a failure occurred */
};
#ifdef WITH_BUFFER_COMPAT
xmlBufCreateStatic(void *mem, size_t size) {
xmlBufPtr ret;
- if ((mem == NULL) || (size == 0))
+ if (mem == NULL)
return(NULL);
ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
* used in the buffer. It does not account for the terminating zero
* usually needed
*
- * Returns the amount or 0 if none or an error occured
+ * Returns the amount or 0 if none or an error occurred
*/
size_t
xmlNsPtr ns,
xmlC14NCtxPtr ctx);
-static int xmlC14NIsNodeInNodeset (xmlNodeSetPtr nodes,
+static int xmlC14NIsNodeInNodeset (void *user_data,
xmlNodePtr node,
xmlNodePtr parent);
#define XML_NAMESPACES_DEFAULT 16
static int
-xmlC14NIsNodeInNodeset(xmlNodeSetPtr nodes, xmlNodePtr node, xmlNodePtr parent) {
+xmlC14NIsNodeInNodeset(void *user_data, xmlNodePtr node, xmlNodePtr parent) {
+ xmlNodeSetPtr nodes = (xmlNodeSetPtr) user_data;
if((nodes != NULL) && (node != NULL)) {
if(node->type != XML_NAMESPACE_DECL) {
return(xmlXPathNodeSetContains(nodes, node));
* Returns -1 if ns1 < ns2, 0 if ns1 == ns2 or 1 if ns1 > ns2.
*/
static int
-xmlC14NNsCompare(xmlNsPtr ns1, xmlNsPtr ns2)
+xmlC14NNsCompare(const void *data1, const void *data2)
{
+ const xmlNsPtr ns1 = (const xmlNsPtr) data1;
+ const xmlNsPtr ns2 = (const xmlNsPtr) data2;
if (ns1 == ns2)
return (0);
if (ns1 == NULL)
return (1);
}
+static int
+xmlC14NPrintNamespacesWalker(const void *ns, void *ctx) {
+ return xmlC14NPrintNamespaces((const xmlNsPtr) ns, (xmlC14NCtxPtr) ctx);
+}
+
/**
* xmlC14NProcessNamespacesAxis:
* @ctx: the C14N context
/*
* Create a sorted list to store element namespaces
*/
- list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare);
+ list = xmlListCreate(NULL, xmlC14NNsCompare);
if (list == NULL) {
xmlC14NErrInternal("creating namespaces list (c14n)");
return (-1);
/*
* print out all elements from list
*/
- xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx);
+ xmlListWalk(list, xmlC14NPrintNamespacesWalker, (void *) ctx);
/*
* Cleanup
/*
* Create a sorted list to store element namespaces
*/
- list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare);
+ list = xmlListCreate(NULL, xmlC14NNsCompare);
if (list == NULL) {
xmlC14NErrInternal("creating namespaces list (exc c14n)");
return (-1);
/*
* print out all elements from list
*/
- xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx);
+ xmlListWalk(list, xmlC14NPrintNamespacesWalker, (void *) ctx);
/*
* Cleanup
* Returns -1 if attr1 < attr2, 0 if attr1 == attr2 or 1 if attr1 > attr2.
*/
static int
-xmlC14NAttrsCompare(xmlAttrPtr attr1, xmlAttrPtr attr2)
+xmlC14NAttrsCompare(const void *data1, const void *data2)
{
+ const xmlAttrPtr attr1 = (const xmlAttrPtr) data1;
+ const xmlAttrPtr attr2 = (const xmlAttrPtr) data2;
int ret = 0;
/*
* Returns 1 on success or 0 on fail.
*/
static int
-xmlC14NPrintAttrs(const xmlAttrPtr attr, xmlC14NCtxPtr ctx)
+xmlC14NPrintAttrs(const void *data, void *user)
{
+ const xmlAttrPtr attr = (const xmlAttrPtr) data;
+ xmlC14NCtxPtr ctx = (xmlC14NCtxPtr) user;
xmlChar *value;
xmlChar *buffer;
/*
* Create a sorted list to store element attributes
*/
- list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NAttrsCompare);
+ list = xmlListCreate(NULL, xmlC14NAttrsCompare);
if (list == NULL) {
xmlC14NErrInternal("creating attributes list");
return (-1);
/*
* print out all elements from list
*/
- xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs, (const void *) ctx);
+ xmlListWalk(list, xmlC14NPrintAttrs, (void *) ctx);
/*
* Cleanup
xmlFreeURI(uri);
return (-1);
}
- if ((xmlStrcasecmp((const xmlChar *) uri->scheme, BAD_CAST "urn") != 0)
- && (xmlStrcasecmp((const xmlChar *) uri->scheme, BAD_CAST "dav") !=0)
- && (xmlStrlen((const xmlChar *) uri->server) == 0)) {
- xmlC14NErrRelativeNamespace(uri->scheme);
- xmlFreeURI(uri);
- return (-1);
- }
xmlFreeURI(uri);
}
ns = ns->next;
return (NULL);
}
- /*
- * Validate the XML document encoding value, if provided.
- */
- if (doc->charset != XML_CHAR_ENCODING_UTF8) {
- xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8,
- "xmlC14NNewCtx: source document not in UTF8\n");
- return (NULL);
- }
-
/*
* Allocate a new xmlC14NCtxPtr and fill the fields.
*/
int mode, xmlChar ** inclusive_ns_prefixes,
int with_comments, xmlOutputBufferPtr buf) {
return(xmlC14NExecute(doc,
- (xmlC14NIsVisibleCallback)xmlC14NIsNodeInNodeset,
+ xmlC14NIsNodeInNodeset,
nodes,
mode,
inclusive_ns_prefixes,
xmlC14NErrParam("saving doc");
return (-1);
}
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if (compression < 0)
compression = xmlGetCompressMode();
#endif
#define MAX_CATAL_DEPTH 50
#ifdef _WIN32
-# define PATH_SEAPARATOR ';'
+# define PATH_SEPARATOR ';'
#else
-# define PATH_SEAPARATOR ':'
+# define PATH_SEPARATOR ':'
#endif
/**
*
* Handle a catalog error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
const char *msg, const xmlChar *str1, const xmlChar *str2,
const xmlChar *str3)
/**
* xmlFreeCatalogEntry:
- * @ret: a Catalog entry
+ * @payload: a Catalog entry
*
* Free the memory allocated to a Catalog entry
*/
static void
-xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
+xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlCatalogEntryPtr ret = (xmlCatalogEntryPtr) payload;
if (ret == NULL)
return;
/*
while (ret != NULL) {
next = ret->next;
- xmlFreeCatalogEntry(ret);
+ xmlFreeCatalogEntry(ret, NULL);
ret = next;
}
}
/**
* xmlFreeCatalogHashEntryList:
- * @ret: a Catalog entry list
+ * @payload: a Catalog entry list
*
* Free the memory allocated to list of Catalog entries from the
* catalog file hash.
*/
static void
-xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) {
+xmlFreeCatalogHashEntryList(void *payload,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlCatalogEntryPtr catal = (xmlCatalogEntryPtr) payload;
xmlCatalogEntryPtr children, next;
if (catal == NULL)
next = children->next;
children->dealloc = 0;
children->children = NULL;
- xmlFreeCatalogEntry(children);
+ xmlFreeCatalogEntry(children, NULL);
children = next;
}
catal->dealloc = 0;
- xmlFreeCatalogEntry(catal);
+ xmlFreeCatalogEntry(catal, NULL);
}
/**
if (catal->xml != NULL)
xmlFreeCatalogEntryList(catal->xml);
if (catal->sgml != NULL)
- xmlHashFree(catal->sgml,
- (xmlHashDeallocator) xmlFreeCatalogEntry);
+ xmlHashFree(catal->sgml, xmlFreeCatalogEntry);
xmlFree(catal);
}
* Serialize an SGML Catalog entry
*/
static void
-xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
+xmlCatalogDumpEntry(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
+ FILE *out = (FILE *) data;
if ((entry == NULL) || (out == NULL))
return;
switch (entry->type) {
* Convert one entry from the catalog
*/
static void
-xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
+xmlCatalogConvertEntry(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
+ xmlCatalogPtr catal = (xmlCatalogPtr) data;
if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
(catal->xml == NULL))
return;
entry->type = XML_CATA_CATALOG;
break;
default:
- xmlHashRemoveEntry(catal->sgml, entry->name,
- (xmlHashDeallocator) xmlFreeCatalogEntry);
+ xmlHashRemoveEntry(catal->sgml, entry->name, xmlFreeCatalogEntry);
return;
}
/*
xmlGenericError(xmlGenericErrorContext,
"Converting SGML catalog to XML\n");
}
- xmlHashScan(catal->sgml,
- (xmlHashScanner) xmlCatalogConvertEntry,
- &catal);
+ xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal);
return(0);
}
case SGML_CATA_ENTITY:
if (*cur == '%')
type = SGML_CATA_PENTITY;
+ /* Falls through. */
case SGML_CATA_PENTITY:
case SGML_CATA_DOCTYPE:
case SGML_CATA_LINKTYPE:
NULL, XML_CATA_PREFER_NONE, NULL);
res = xmlHashAddEntry(catal->sgml, name, entry);
if (res < 0) {
- xmlFreeCatalogEntry(entry);
+ xmlFreeCatalogEntry(entry, NULL);
}
xmlFree(filename);
}
XML_CATA_PREFER_NONE, NULL);
res = xmlHashAddEntry(catal->sgml, sysid, entry);
if (res < 0) {
- xmlFreeCatalogEntry(entry);
+ xmlFreeCatalogEntry(entry, NULL);
}
} else {
xmlChar *filename;
if (catal->type == XML_XML_CATALOG_TYPE) {
xmlDumpXMLCatalog(out, catal->xml);
} else {
- xmlHashScan(catal->sgml,
- (xmlHashScanner) xmlCatalogDumpEntry, out);
+ xmlHashScan(catal->sgml, xmlCatalogDumpEntry, out);
}
}
#endif /* LIBXML_OUTPUT_ENABLED */
if (catal->type == XML_XML_CATALOG_TYPE) {
res = xmlDelXMLCatalog(catal->xml, value);
} else {
- res = xmlHashRemoveEntry(catal->sgml, value,
- (xmlHashDeallocator) xmlFreeCatalogEntry);
+ res = xmlHashRemoveEntry(catal->sgml, value, xmlFreeCatalogEntry);
if (res == 0)
res = 1;
}
while (xmlIsBlank_ch(*cur)) cur++;
if (*cur != 0) {
paths = cur;
- while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
+ while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
cur++;
path = xmlStrndup((const xmlChar *)paths, cur - paths);
#ifdef _WIN32
xmlFree(path);
}
}
- while (*cur == PATH_SEAPARATOR)
+ while (*cur == PATH_SEPARATOR)
cur++;
}
}
xmlGenericError(xmlGenericErrorContext,
"Catalogs cleanup\n");
if (xmlCatalogXMLFiles != NULL)
- xmlHashFree(xmlCatalogXMLFiles,
- (xmlHashDeallocator)xmlFreeCatalogHashEntryList);
+ xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList);
xmlCatalogXMLFiles = NULL;
if (xmlDefaultCatalog != NULL)
xmlFreeCatalog(xmlDefaultCatalog);
int depth; /* current depth */
xmlDocPtr doc; /* current document */
xmlNodePtr node; /* current node */
- xmlDictPtr dict; /* the doc dictionnary */
+ xmlDictPtr dict; /* the doc dictionary */
int check; /* do just checkings */
int errors; /* number of errors found */
- int nodict; /* if the document has no dictionnary */
+ int nodict; /* if the document has no dictionary */
int options; /* options */
};
NULL, NULL, NULL, 0, 0,
"%s", msg);
}
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
{
ctxt->errors++;
NULL, NULL, NULL, 0, 0,
msg, extra);
}
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
{
ctxt->errors++;
* @ctxt: the debug context
* @name: the name
*
- * Do debugging on the name, for example the dictionnary status and
+ * Do debugging on the name, for example the dictionary status and
* conformance to the Name production.
*/
static void
((ctxt->doc == NULL) ||
((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
- "Name is not from the document dictionnary '%s'",
+ "Name is not from the document dictionary '%s'",
(const char *) name);
}
}
/* desactivated right now as it raises too many errors */
if (doc->type == XML_DOCUMENT_NODE)
xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
- "Document has no dictionnary\n");
+ "Document has no dictionary\n");
#endif
ctxt->nodict = 1;
}
}
static void
-xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
+xmlCtxtDumpEntityCallback(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED)
{
+ xmlEntityPtr cur = (xmlEntityPtr) payload;
+ xmlDebugCtxtPtr ctxt = (xmlDebugCtxtPtr) data;
if (cur == NULL) {
if (!ctxt->check)
fprintf(ctxt->output, "Entity is NULL");
if (!ctxt->check)
fprintf(ctxt->output, "Entities in internal subset\n");
- xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
- ctxt);
+ xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
} else
fprintf(ctxt->output, "No entities in internal subset\n");
if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
if (!ctxt->check)
fprintf(ctxt->output, "Entities in external subset\n");
- xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
- ctxt);
+ xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
} else if (!ctxt->check)
fprintf(ctxt->output, "No entities in external subset\n");
}
fprintf(ctxt->output, "\tvalidate check the document for errors\n");
#endif /* LIBXML_VALID_ENABLED */
#ifdef LIBXML_SCHEMAS_ENABLED
- fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
+ fprintf(ctxt->output, "\trelaxng rng validate the document against the Relax-NG schemas\n");
#endif
fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
#ifdef LIBXML_VALID_ENABLED
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
-#elif defined(WIN32)
+#elif defined(_WIN32)
typedef unsigned __int32 uint32_t;
#endif
#endif
#endif /* WITH_BIG_KEY */
/*
- * An entry in the dictionnary
+ * An entry in the dictionary
*/
typedef struct _xmlDictEntry xmlDictEntry;
typedef xmlDictEntry *xmlDictEntryPtr;
xmlChar array[1];
};
/*
- * The entire dictionnary
+ * The entire dictionary
*/
struct _xmlDict {
int ref_counter;
/*
* xmlDictAddString:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @name: the name of the userdata
* @len: the length of the name
*
#endif
pool = dict->strings;
while (pool != NULL) {
- if (pool->end - pool->free > namelen)
+ if ((size_t)(pool->end - pool->free) > namelen)
goto found_pool;
if (pool->size > size) size = pool->size;
limit += pool->size;
/*
* xmlDictAddQString:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @prefix: the prefix of the userdata
* @plen: the prefix length
* @name: the name of the userdata
#endif
pool = dict->strings;
while (pool != NULL) {
- if (pool->end - pool->free > namelen + plen + 1)
+ if ((size_t)(pool->end - pool->free) > namelen + plen + 1)
goto found_pool;
if (pool->size > size) size = pool->size;
limit += pool->size;
}
switch (namelen) {
case 10: value += name[9];
+ /* Falls through. */
case 9: value += name[8];
+ /* Falls through. */
case 8: value += name[7];
+ /* Falls through. */
case 7: value += name[6];
+ /* Falls through. */
case 6: value += name[5];
+ /* Falls through. */
case 5: value += name[4];
+ /* Falls through. */
case 4: value += name[3];
+ /* Falls through. */
case 3: value += name[2];
+ /* Falls through. */
case 2: value += name[1];
+ /* Falls through. */
default: break;
}
return(value);
}
switch (plen) {
case 10: value += prefix[9];
+ /* Falls through. */
case 9: value += prefix[8];
+ /* Falls through. */
case 8: value += prefix[7];
+ /* Falls through. */
case 7: value += prefix[6];
+ /* Falls through. */
case 6: value += prefix[5];
+ /* Falls through. */
case 5: value += prefix[4];
+ /* Falls through. */
case 4: value += prefix[3];
+ /* Falls through. */
case 3: value += prefix[2];
+ /* Falls through. */
case 2: value += prefix[1];
+ /* Falls through. */
case 1: value += prefix[0];
+ /* Falls through. */
default: break;
}
len -= plen;
}
switch (len) {
case 10: value += name[9];
+ /* Falls through. */
case 9: value += name[8];
+ /* Falls through. */
case 8: value += name[7];
+ /* Falls through. */
case 7: value += name[6];
+ /* Falls through. */
case 6: value += name[5];
+ /* Falls through. */
case 5: value += name[4];
+ /* Falls through. */
case 4: value += name[3];
+ /* Falls through. */
case 3: value += name[2];
+ /* Falls through. */
case 2: value += name[1];
+ /* Falls through. */
case 1: value += name[0];
+ /* Falls through. */
default: break;
}
return(value);
*
* Create a new dictionary
*
- * Returns the newly created dictionnary, or NULL if an error occured.
+ * Returns the newly created dictionary, or NULL if an error occurred.
*/
xmlDictPtr
xmlDictCreate(void) {
/**
* xmlDictCreateSub:
- * @sub: an existing dictionnary
+ * @sub: an existing dictionary
*
* Create a new dictionary, inheriting strings from the read-only
- * dictionnary @sub. On lookup, strings are first searched in the
- * new dictionnary, then in @sub, and if not found are created in the
- * new dictionnary.
+ * dictionary @sub. On lookup, strings are first searched in the
+ * new dictionary, then in @sub, and if not found are created in the
+ * new dictionary.
*
- * Returns the newly created dictionnary, or NULL if an error occured.
+ * Returns the newly created dictionary, or NULL if an error occurred.
*/
xmlDictPtr
xmlDictCreateSub(xmlDictPtr sub) {
/**
* xmlDictReference:
- * @dict: the dictionnary
+ * @dict: the dictionary
*
* Increment the reference counter of a dictionary
*
/**
* xmlDictGrow:
- * @dict: the dictionnary
- * @size: the new size of the dictionnary
+ * @dict: the dictionary
+ * @size: the new size of the dictionary
*
- * resize the dictionnary
+ * resize the dictionary
*
* Returns 0 in case of success, -1 in case of failure
*/
} else {
/*
* we don't have much ways to alert from herei
- * result is loosing an entry and unicity garantee
+ * result is losing an entry and unicity guarantee
*/
ret = -1;
}
/**
* xmlDictFree:
- * @dict: the dictionnary
+ * @dict: the dictionary
*
* Free the hash @dict and its contents. The userdata is
* deallocated with @f if provided.
/**
* xmlDictLookup:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @name: the name of the userdata
* @len: the length of the name, if -1 it is recomputed
*
- * Add the @name to the dictionnary @dict if not present.
+ * Add the @name to the dictionary @dict if not present.
*
* Returns the internal copy of the name or NULL in case of internal error
*/
/**
* xmlDictExists:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @name: the name of the userdata
* @len: the length of the name, if -1 it is recomputed
*
- * Check if the @name exists in the dictionnary @dict.
+ * Check if the @name exists in the dictionary @dict.
*
* Returns the internal copy of the name or NULL if not found.
*/
/**
* xmlDictQLookup:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @prefix: the prefix
* @name: the name
*
/**
* xmlDictOwns:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @str: the string
*
* check if a string is owned by the disctionary
/**
* xmlDictSize:
- * @dict: the dictionnary
+ * @dict: the dictionary
*
* Query the number of elements installed in the hash @dict.
*
- * Returns the number of elements in the dictionnary or
+ * Returns the number of elements in the dictionary or
* -1 in case of error
*/
int
/**
* xmlDictSetLimit:
- * @dict: the dictionnary
+ * @dict: the dictionary
* @limit: the limit in bytes
*
* Set a size limit for the dictionary
/**
* xmlDictGetUsage:
- * @dict: the dictionnary
+ * @dict: the dictionary
*
* Get how much memory is used by a dictionary for strings
* Added in 2.9.0
/*
- * Summary: string dictionnary
+ * Summary: string dictionary
* Description: dictionary of reusable strings, just used to avoid allocation
* and freeing operations.
*
#ifndef __XML_DICT_H__
#define __XML_DICT_H__
+#ifdef __cplusplus
+#define __XML_EXTERNC extern "C"
+#else
+#define __XML_EXTERNC
+#endif
+
+/*
+ * The dictionary.
+ */
+__XML_EXTERNC typedef struct _xmlDict xmlDict;
+__XML_EXTERNC typedef xmlDict *xmlDictPtr;
+
#include <limits.h>
#include <libxml/xmlversion.h>
#include <libxml/tree.h>
extern "C" {
#endif
-/*
- * The dictionnary.
- */
-typedef struct _xmlDict xmlDict;
-typedef xmlDict *xmlDictPtr;
-
/*
* Initializer
*/
xmlDictFree (xmlDictPtr dict);
/*
- * Lookup of entry in the dictionnary.
+ * Lookup of entry in the dictionary.
*/
XMLPUBFUN const xmlChar * XMLCALL
xmlDictLookup (xmlDictPtr dict,
#if defined IN_LIBXML && !defined IN_LIBTEXTSTYLE
#ifdef __GNUC__
#ifdef PIC
-#ifdef linux
+#ifdef __linux__
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
#include "libxml/c14n.h"
*
* n encoding error
*/
-static void
+static void LIBXML_ATTR_FORMAT(2,0)
xmlEncodingErr(xmlParserErrors error, const char *msg, const char *val)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL,
if (conv == NULL)
return NULL;
+ conv->pivot_source = conv->pivot_buf;
+ conv->pivot_target = conv->pivot_buf;
+
conv->uconv = ucnv_open(name, &status);
if (U_FAILURE(status))
goto error;
{
int len;
- if ((out == NULL) || (inb == NULL) || (outlen == NULL) || (inlenb == NULL))
+ if ((out == NULL) || (outlen == NULL) || (inlenb == NULL))
return(-1);
+ if (inb == NULL) {
+ /* inb == NULL means output is initialized. */
+ *outlen = 0;
+ *inlenb = 0;
+ return(0);
+ }
if (*outlen > *inlenb) {
len = *inlenb;
} else {
* @outlen: the length of @out
* @in: a pointer to an array of ISO Latin 1 chars
* @inlen: the length of @in
+ * @flush: if true, indicates end of input
*
* Returns 0 if success, or
* -1 by lack of space, or
*/
static int
xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
- const unsigned char *in, int *inlen) {
+ const unsigned char *in, int *inlen, int flush) {
const char *ucv_in = (const char *) in;
char *ucv_out = (char *) out;
UErrorCode err = U_ZERO_ERROR;
return(-1);
}
- /*
- * TODO(jungshik)
- * 1. is ucnv_convert(To|From)Algorithmic better?
- * 2. had we better use an explicit pivot buffer?
- * 3. error returned comes from 'fromUnicode' only even
- * when toUnicode is true !
- */
if (toUnicode) {
/* encoding => UTF-16 => UTF-8 */
ucnv_convertEx(cd->utf8, cd->uconv, &ucv_out, ucv_out + *outlen,
- &ucv_in, ucv_in + *inlen, NULL, NULL, NULL, NULL,
- 0, TRUE, &err);
+ &ucv_in, ucv_in + *inlen, cd->pivot_buf,
+ &cd->pivot_source, &cd->pivot_target,
+ cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
} else {
/* UTF-8 => UTF-16 => encoding */
ucnv_convertEx(cd->uconv, cd->utf8, &ucv_out, ucv_out + *outlen,
- &ucv_in, ucv_in + *inlen, NULL, NULL, NULL, NULL,
- 0, TRUE, &err);
+ &ucv_in, ucv_in + *inlen, cd->pivot_buf,
+ &cd->pivot_source, &cd->pivot_target,
+ cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
}
*inlen = ucv_in - (const char*) in;
*outlen = ucv_out - (char *) out;
- if (U_SUCCESS(err))
+ if (U_SUCCESS(err)) {
+ /* reset pivot buf if this is the last call for input (flush==TRUE) */
+ if (flush)
+ cd->pivot_source = cd->pivot_target = cd->pivot_buf;
return 0;
+ }
if (err == U_BUFFER_OVERFLOW_ERROR)
return -1;
if (err == U_INVALID_CHAR_FOUND || err == U_ILLEGAL_CHAR_FOUND)
return -2;
- /* if (err == U_TRUNCATED_CHAR_FOUND) */
return -3;
}
#endif /* LIBXML_ICU_ENABLED */
* *
************************************************************************/
+static int
+xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
+ int *outlen, const unsigned char *in, int *inlen, int flush) {
+ int ret;
+ (void)flush;
+
+ if (handler->input != NULL) {
+ ret = handler->input(out, outlen, in, inlen);
+ }
+#ifdef LIBXML_ICONV_ENABLED
+ else if (handler->iconv_in != NULL) {
+ ret = xmlIconvWrapper(handler->iconv_in, out, outlen, in, inlen);
+ }
+#endif /* LIBXML_ICONV_ENABLED */
+#ifdef LIBXML_ICU_ENABLED
+ else if (handler->uconv_in != NULL) {
+ ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen,
+ flush);
+ }
+#endif /* LIBXML_ICU_ENABLED */
+ else {
+ *outlen = 0;
+ *inlen = 0;
+ ret = -2;
+ }
+
+ return(ret);
+}
+
+/* Returns -4 if no output function was found. */
+static int
+xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
+ int *outlen, const unsigned char *in, int *inlen) {
+ int ret;
+
+ if (handler->output != NULL) {
+ ret = handler->output(out, outlen, in, inlen);
+ }
+#ifdef LIBXML_ICONV_ENABLED
+ else if (handler->iconv_out != NULL) {
+ ret = xmlIconvWrapper(handler->iconv_out, out, outlen, in, inlen);
+ }
+#endif /* LIBXML_ICONV_ENABLED */
+#ifdef LIBXML_ICU_ENABLED
+ else if (handler->uconv_out != NULL) {
+ ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen,
+ TRUE);
+ }
+#endif /* LIBXML_ICU_ENABLED */
+ else {
+ *outlen = 0;
+ *inlen = 0;
+ ret = -4;
+ }
+
+ return(ret);
+}
+
/**
* xmlCharEncFirstLineInt:
* @handler: char enconding transformation data structure
int
xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out,
xmlBufferPtr in, int len) {
- int ret = -2;
+ int ret;
int written;
int toconv;
written = out->size - out->use - 1;
}
- if (handler->input != NULL) {
- ret = handler->input(&out->content[out->use], &written,
- in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (handler->iconv_in != NULL) {
- ret = xmlIconvWrapper(handler->iconv_in, &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- if (ret == -1) ret = -3;
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (handler->uconv_in != NULL) {
- ret = xmlUconvWrapper(handler->uconv_in, 1, &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- if (ret == -1) ret = -3;
- }
-#endif /* LIBXML_ICU_ENABLED */
+ ret = xmlEncInputChunk(handler, &out->content[out->use], &written,
+ in->content, &toconv, 0);
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ if (ret == -1) ret = -3;
+
#ifdef DEBUG_ENCODING
switch (ret) {
case 0:
int
xmlCharEncFirstLineInput(xmlParserInputBufferPtr input, int len)
{
- int ret = -2;
+ int ret;
size_t written;
size_t toconv;
int c_in;
c_in = toconv;
c_out = written;
- if (input->encoder->input != NULL) {
- ret = input->encoder->input(xmlBufEnd(out), &c_out,
- xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (input->encoder->iconv_in != NULL) {
- ret = xmlIconvWrapper(input->encoder->iconv_in, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (input->encoder->uconv_in != NULL) {
- ret = xmlUconvWrapper(input->encoder->uconv_in, 1, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICU_ENABLED */
+ ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
+ xmlBufContent(in), &c_in, 0);
+ xmlBufShrink(in, c_in);
+ xmlBufAddLen(out, c_out);
+ if (ret == -1)
+ ret = -3;
+
switch (ret) {
case 0:
#ifdef DEBUG_ENCODING
int
xmlCharEncInput(xmlParserInputBufferPtr input, int flush)
{
- int ret = -2;
+ int ret;
size_t written;
size_t toconv;
int c_in;
c_in = toconv;
c_out = written;
- if (input->encoder->input != NULL) {
- ret = input->encoder->input(xmlBufEnd(out), &c_out,
- xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (input->encoder->iconv_in != NULL) {
- ret = xmlIconvWrapper(input->encoder->iconv_in, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (input->encoder->uconv_in != NULL) {
- ret = xmlUconvWrapper(input->encoder->uconv_in, 1, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICU_ENABLED */
+ ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
+ xmlBufContent(in), &c_in, flush);
+ xmlBufShrink(in, c_in);
+ xmlBufAddLen(out, c_out);
+ if (ret == -1)
+ ret = -3;
+
switch (ret) {
case 0:
#ifdef DEBUG_ENCODING
xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
xmlBufferPtr in)
{
- int ret = -2;
+ int ret;
int written;
int toconv;
xmlBufferGrow(out, out->size + toconv * 2);
written = out->size - out->use - 1;
}
- if (handler->input != NULL) {
- ret = handler->input(&out->content[out->use], &written,
- in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (handler->iconv_in != NULL) {
- ret = xmlIconvWrapper(handler->iconv_in, &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (handler->uconv_in != NULL) {
- ret = xmlUconvWrapper(handler->uconv_in, 1, &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- out->content[out->use] = 0;
- if (ret == -1)
- ret = -3;
- }
-#endif /* LIBXML_ICU_ENABLED */
+ ret = xmlEncInputChunk(handler, &out->content[out->use], &written,
+ in->content, &toconv, 1);
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ if (ret == -1)
+ ret = -3;
+
switch (ret) {
case 0:
#ifdef DEBUG_ENCODING
int
xmlCharEncOutput(xmlOutputBufferPtr output, int init)
{
- int ret = -2;
+ int ret;
size_t written;
size_t writtentot = 0;
size_t toconv;
int c_out;
xmlBufPtr in;
xmlBufPtr out;
- int charref_len = 0;
if ((output == NULL) || (output->encoder == NULL) ||
(output->buffer == NULL) || (output->conv == NULL))
if (init) {
c_in = 0;
c_out = written;
- if (output->encoder->output != NULL) {
- ret = output->encoder->output(xmlBufEnd(out), &c_out,
- NULL, &c_in);
- if (ret > 0) /* Gennady: check return value */
- xmlBufAddLen(out, c_out);
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (output->encoder->iconv_out != NULL) {
- ret = xmlIconvWrapper(output->encoder->iconv_out, xmlBufEnd(out),
- &c_out, NULL, &c_in);
- xmlBufAddLen(out, c_out);
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (output->encoder->uconv_out != NULL) {
- ret = xmlUconvWrapper(output->encoder->uconv_out, 0, xmlBufEnd(out),
- &c_out, NULL, &c_in);
- xmlBufAddLen(out, c_out);
- }
-#endif /* LIBXML_ICU_ENABLED */
+ /* TODO: Check return value. */
+ xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
+ NULL, &c_in);
+ xmlBufAddLen(out, c_out);
#ifdef DEBUG_ENCODING
xmlGenericError(xmlGenericErrorContext,
"initialized encoder\n");
c_in = toconv;
c_out = written;
- if (output->encoder->output != NULL) {
- ret = output->encoder->output(xmlBufEnd(out), &c_out,
- xmlBufContent(in), &c_in);
+ ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
+ xmlBufContent(in), &c_in);
+ xmlBufShrink(in, c_in);
+ xmlBufAddLen(out, c_out);
+ writtentot += c_out;
+ if (ret == -1) {
if (c_out > 0) {
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- writtentot += c_out;
- }
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (output->encoder->iconv_out != NULL) {
- ret = xmlIconvWrapper(output->encoder->iconv_out, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- writtentot += c_out;
- if (ret == -1) {
- if (c_out > 0) {
- /*
- * Can be a limitation of iconv
- */
- charref_len = 0;
- goto retry;
- }
- ret = -3;
- }
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (output->encoder->uconv_out != NULL) {
- ret = xmlUconvWrapper(output->encoder->uconv_out, 0, xmlBufEnd(out),
- &c_out, xmlBufContent(in), &c_in);
- xmlBufShrink(in, c_in);
- xmlBufAddLen(out, c_out);
- writtentot += c_out;
- if (ret == -1) {
- if (c_out > 0) {
- /*
- * Can be a limitation of uconv
- */
- charref_len = 0;
- goto retry;
- }
- ret = -3;
+ /* Can be a limitation of iconv or uconv */
+ goto retry;
}
+ ret = -3;
}
-#endif /* LIBXML_ICU_ENABLED */
- else {
- xmlEncodingErr(XML_I18N_NO_OUTPUT,
- "xmlCharEncOutFunc: no output function !\n", NULL);
- return(-1);
- }
-
- if (ret >= 0) output += ret;
/*
* Attempt to handle error cases
c_in, c_out, (int) xmlBufUse(in));
#endif
break;
+ case -4:
+ xmlEncodingErr(XML_I18N_NO_OUTPUT,
+ "xmlCharEncOutFunc: no output function !\n", NULL);
+ ret = -1;
+ break;
case -2: {
+ xmlChar charref[20];
int len = (int) xmlBufUse(in);
xmlChar *content = xmlBufContent(in);
- int cur;
+ int cur, charrefLen;
cur = xmlGetUTF8Char(content, &len);
- if ((charref_len != 0) && (c_out < charref_len)) {
- /*
- * We attempted to insert a character reference and failed.
- * Undo what was written and skip the remaining charref.
- */
- xmlBufErase(out, c_out);
- writtentot -= c_out;
- xmlBufShrink(in, charref_len - c_out);
- charref_len = 0;
-
- ret = -1;
+ if (cur <= 0)
break;
- } else if (cur > 0) {
- xmlChar charref[20];
#ifdef DEBUG_ENCODING
- xmlGenericError(xmlGenericErrorContext,
- "handling output conversion error\n");
- xmlGenericError(xmlGenericErrorContext,
- "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
- content[0], content[1],
- content[2], content[3]);
+ xmlGenericError(xmlGenericErrorContext,
+ "handling output conversion error\n");
+ xmlGenericError(xmlGenericErrorContext,
+ "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ content[0], content[1],
+ content[2], content[3]);
#endif
- /*
- * Removes the UTF8 sequence, and replace it by a charref
- * and continue the transcoding phase, hoping the error
- * did not mangle the encoder state.
- */
- charref_len = snprintf((char *) &charref[0], sizeof(charref),
- "&#%d;", cur);
- xmlBufShrink(in, len);
- xmlBufAddHead(in, charref, -1);
-
- goto retry;
- } else {
+ /*
+ * Removes the UTF8 sequence, and replace it by a charref
+ * and continue the transcoding phase, hoping the error
+ * did not mangle the encoder state.
+ */
+ charrefLen = snprintf((char *) &charref[0], sizeof(charref),
+ "&#%d;", cur);
+ xmlBufShrink(in, len);
+ xmlBufGrow(out, charrefLen * 4);
+ c_out = xmlBufAvail(out) - 1;
+ c_in = charrefLen;
+ ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
+ charref, &c_in);
+
+ if ((ret < 0) || (c_in != charrefLen)) {
char buf[50];
snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
buf);
if (xmlBufGetAllocationScheme(in) != XML_BUFFER_ALLOC_IMMUTABLE)
content[0] = ' ';
+ break;
}
- break;
+
+ xmlBufAddLen(out, c_out);
+ writtentot += c_out;
+ goto retry;
}
}
return(ret);
int
xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
xmlBufferPtr in) {
- int ret = -2;
+ int ret;
int written;
int writtentot = 0;
int toconv;
int output = 0;
- int charref_len = 0;
if (handler == NULL) return(-1);
if (out == NULL) return(-1);
*/
if (in == NULL) {
toconv = 0;
- if (handler->output != NULL) {
- ret = handler->output(&out->content[out->use], &written,
- NULL, &toconv);
- if (ret >= 0) { /* Gennady: check return value */
- out->use += written;
- out->content[out->use] = 0;
- }
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (handler->iconv_out != NULL) {
- ret = xmlIconvWrapper(handler->iconv_out, &out->content[out->use],
- &written, NULL, &toconv);
- out->use += written;
- out->content[out->use] = 0;
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (handler->uconv_out != NULL) {
- ret = xmlUconvWrapper(handler->uconv_out, 0,
- &out->content[out->use],
- &written, NULL, &toconv);
- out->use += written;
- out->content[out->use] = 0;
- }
-#endif /* LIBXML_ICU_ENABLED */
+ /* TODO: Check return value. */
+ xmlEncOutputChunk(handler, &out->content[out->use], &written,
+ NULL, &toconv);
+ out->use += written;
+ out->content[out->use] = 0;
#ifdef DEBUG_ENCODING
xmlGenericError(xmlGenericErrorContext,
"initialized encoder\n");
xmlBufferGrow(out, toconv * 4);
written = out->size - out->use - 1;
}
- if (handler->output != NULL) {
- ret = handler->output(&out->content[out->use], &written,
- in->content, &toconv);
- if (written > 0) {
- xmlBufferShrink(in, toconv);
- out->use += written;
- writtentot += written;
- }
- out->content[out->use] = 0;
- }
-#ifdef LIBXML_ICONV_ENABLED
- else if (handler->iconv_out != NULL) {
- ret = xmlIconvWrapper(handler->iconv_out, &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- writtentot += written;
- out->content[out->use] = 0;
- if (ret == -1) {
- if (written > 0) {
- /*
- * Can be a limitation of iconv
- */
- charref_len = 0;
- goto retry;
- }
- ret = -3;
- }
- }
-#endif /* LIBXML_ICONV_ENABLED */
-#ifdef LIBXML_ICU_ENABLED
- else if (handler->uconv_out != NULL) {
- ret = xmlUconvWrapper(handler->uconv_out, 0,
- &out->content[out->use],
- &written, in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- writtentot += written;
- out->content[out->use] = 0;
- if (ret == -1) {
- if (written > 0) {
- /*
- * Can be a limitation of iconv
- */
- charref_len = 0;
- goto retry;
- }
- ret = -3;
- }
- }
-#endif /* LIBXML_ICU_ENABLED */
- else {
- xmlEncodingErr(XML_I18N_NO_OUTPUT,
- "xmlCharEncOutFunc: no output function !\n", NULL);
- return(-1);
+ ret = xmlEncOutputChunk(handler, &out->content[out->use], &written,
+ in->content, &toconv);
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ writtentot += written;
+ out->content[out->use] = 0;
+ if (ret == -1) {
+ if (written > 0) {
+ /* Can be a limitation of iconv or uconv */
+ goto retry;
+ }
+ ret = -3;
}
if (ret >= 0) output += ret;
toconv, written, in->use);
#endif
break;
+ case -4:
+ xmlEncodingErr(XML_I18N_NO_OUTPUT,
+ "xmlCharEncOutFunc: no output function !\n", NULL);
+ ret = -1;
+ break;
case -2: {
+ xmlChar charref[20];
int len = in->use;
const xmlChar *utf = (const xmlChar *) in->content;
- int cur;
+ int cur, charrefLen;
cur = xmlGetUTF8Char(utf, &len);
- if ((charref_len != 0) && (written < charref_len)) {
- /*
- * We attempted to insert a character reference and failed.
- * Undo what was written and skip the remaining charref.
- */
- out->use -= written;
- writtentot -= written;
- xmlBufferShrink(in, charref_len - written);
- charref_len = 0;
-
- ret = -1;
+ if (cur <= 0)
break;
- } else if (cur > 0) {
- xmlChar charref[20];
#ifdef DEBUG_ENCODING
- xmlGenericError(xmlGenericErrorContext,
- "handling output conversion error\n");
- xmlGenericError(xmlGenericErrorContext,
- "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
- in->content[0], in->content[1],
- in->content[2], in->content[3]);
+ xmlGenericError(xmlGenericErrorContext,
+ "handling output conversion error\n");
+ xmlGenericError(xmlGenericErrorContext,
+ "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ in->content[0], in->content[1],
+ in->content[2], in->content[3]);
#endif
- /*
- * Removes the UTF8 sequence, and replace it by a charref
- * and continue the transcoding phase, hoping the error
- * did not mangle the encoder state.
- */
- charref_len = snprintf((char *) &charref[0], sizeof(charref),
- "&#%d;", cur);
- xmlBufferShrink(in, len);
- xmlBufferAddHead(in, charref, -1);
-
- goto retry;
- } else {
+ /*
+ * Removes the UTF8 sequence, and replace it by a charref
+ * and continue the transcoding phase, hoping the error
+ * did not mangle the encoder state.
+ */
+ charrefLen = snprintf((char *) &charref[0], sizeof(charref),
+ "&#%d;", cur);
+ xmlBufferShrink(in, len);
+ xmlBufferGrow(out, charrefLen * 4);
+ written = out->size - out->use - 1;
+ toconv = charrefLen;
+ ret = xmlEncOutputChunk(handler, &out->content[out->use], &written,
+ charref, &toconv);
+
+ if ((ret < 0) || (toconv != charrefLen)) {
char buf[50];
snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X",
buf);
if (in->alloc != XML_BUFFER_ALLOC_IMMUTABLE)
in->content[0] = ' ';
+ break;
}
- break;
+
+ out->use += written;
+ writtentot += written;
+ out->content[out->use] = 0;
+ goto retry;
}
}
return(ret);
int ret;
- if (handler->output != NULL) {
- do {
- toconv = in->end - cur;
- written = 32000;
- ret = handler->output(&convbuf[0], &written,
- cur, &toconv);
- if (ret == -1) return(-1);
- unused += written;
- cur += toconv;
- } while (ret == -2);
-#ifdef LIBXML_ICONV_ENABLED
- } else if (handler->iconv_out != NULL) {
- do {
- toconv = in->end - cur;
- written = 32000;
- ret = xmlIconvWrapper(handler->iconv_out, &convbuf[0],
- &written, cur, &toconv);
- if (ret < 0) {
- if (written > 0)
- ret = -2;
- else
- return(-1);
- }
- unused += written;
- cur += toconv;
- } while (ret == -2);
-#endif
-#ifdef LIBXML_ICU_ENABLED
- } else if (handler->uconv_out != NULL) {
- do {
- toconv = in->end - cur;
- written = 32000;
- ret = xmlUconvWrapper(handler->uconv_out, 0, &convbuf[0],
- &written, cur, &toconv);
- if (ret < 0) {
- if (written > 0)
- ret = -2;
- else
- return(-1);
- }
- unused += written;
- cur += toconv;
- } while (ret == -2);
-#endif
- } else {
- /* could not find a converter */
- return(-1);
- }
+ do {
+ toconv = in->end - cur;
+ written = 32000;
+ ret = xmlEncOutputChunk(handler, &convbuf[0], &written,
+ cur, &toconv);
+ if (ret < 0) {
+ if (written > 0)
+ ret = -2;
+ else
+ return(-1);
+ }
+ unused += written;
+ cur += toconv;
+ } while (ret == -2);
}
if (in->buf->rawconsumed < unused)
return(-1);
* If iconv is supported, there are two extra fields.
*/
#ifdef LIBXML_ICU_ENABLED
+/* Size of pivot buffer, same as icu/source/common/ucnv.cpp CHUNK_SIZE */
+#define ICU_PIVOT_BUF_SIZE 1024
struct _uconv_t {
UConverter *uconv; /* for conversion between an encoding and UTF-16 */
UConverter *utf8; /* for conversion between UTF-8 and UTF-16 */
+ UChar pivot_buf[ICU_PIVOT_BUF_SIZE];
+ UChar *pivot_source;
+ UChar *pivot_target;
};
typedef struct _uconv_t uconv_t;
#endif
* daniel@veillard.com
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
*
* Handle an out of memory condition
*/
-static void
+static void LIBXML_ATTR_FORMAT(2,0)
xmlEntitiesErr(xmlParserErrors code, const char *msg)
{
__xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL);
* Deallocate the memory used by an entities in the hash table.
*/
static void
-xmlFreeEntityWrapper(xmlEntityPtr entity,
- const xmlChar *name ATTRIBUTE_UNUSED) {
+xmlFreeEntityWrapper(void *entity, const xmlChar *name ATTRIBUTE_UNUSED) {
if (entity != NULL)
- xmlFreeEntity(entity);
+ xmlFreeEntity((xmlEntityPtr) entity);
}
/**
*/
void
xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeEntityWrapper);
+ xmlHashFree(table, xmlFreeEntityWrapper);
}
#ifdef LIBXML_TREE_ENABLED
*
* Returns the new xmlEntitiesPtr or NULL in case of error.
*/
-static xmlEntityPtr
-xmlCopyEntity(xmlEntityPtr ent) {
+static void *
+xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlEntityPtr ent = (xmlEntityPtr) payload;
xmlEntityPtr cur;
cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
*/
xmlEntitiesTablePtr
xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
- return(xmlHashCopy(table, (xmlHashCopier) xmlCopyEntity));
+ return(xmlHashCopy(table, xmlCopyEntity));
}
#endif /* LIBXML_TREE_ENABLED */
* When using the hash table scan function, arguments need to be reversed
*/
static void
-xmlDumpEntityDeclScan(xmlEntityPtr ent, xmlBufferPtr buf) {
- xmlDumpEntityDecl(buf, ent);
+xmlDumpEntityDeclScan(void *ent, void *buf,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlDumpEntityDecl((xmlBufferPtr) buf, (xmlEntityPtr) ent);
}
/**
*/
void
xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
- xmlHashScan(table, (xmlHashScanner)xmlDumpEntityDeclScan, buf);
+ xmlHashScan(table, xmlDumpEntityDeclScan, buf);
}
#endif /* LIBXML_OUTPUT_ENABLED */
#define bottom_entities
void XMLCDECL xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
const char *msg,
- ...);
+ ...) LIBXML_ATTR_FORMAT(2,3);
#define XML_GET_VAR_STR(msg, str) { \
int size, prev_size = -1; \
xmlChar content[81]; /* space for 80 chars + line terminator */
xmlChar *ctnt;
- if ((input == NULL) || (input->cur == NULL) ||
- (*input->cur == 0)) return;
+ if ((input == NULL) || (input->cur == NULL))
+ return;
cur = input->cur;
base = input->base;
* Get the last global error registered. This is per thread if compiled
* with thread support.
*
- * Returns NULL if no error occured or a pointer to the error
+ * Returns NULL if no error occurred or a pointer to the error
*/
xmlErrorPtr
xmlGetLastError(void)
*
* Get the last parsing error registered.
*
- * Returns NULL if no error occured or a pointer to the error
+ * Returns NULL if no error occurred or a pointer to the error
*/
xmlErrorPtr
xmlCtxtGetLastError(void *ctx)
*
* The variable holding the libxml free() implementation
*/
-xmlFreeFunc xmlFree = (xmlFreeFunc) free;
+xmlFreeFunc xmlFree = free;
/**
* xmlMalloc:
* @size: the size requested in bytes
*
* Returns a pointer to the newly allocated block or NULL in case of error
*/
-xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
+xmlMallocFunc xmlMalloc = malloc;
/**
* xmlMallocAtomic:
* @size: the size requested in bytes
*
* Returns a pointer to the newly allocated block or NULL in case of error
*/
-xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) malloc;
+xmlMallocFunc xmlMallocAtomic = malloc;
/**
* xmlRealloc:
* @mem: an already allocated block of memory
*
* Returns a pointer to the newly reallocated block or NULL in case of error
*/
-xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
+xmlReallocFunc xmlRealloc = realloc;
+/**
+ * xmlPosixStrdup
+ * @cur: the input char *
+ *
+ * a strdup implementation with a type signature matching POSIX
+ *
+ * Returns a new xmlChar * or NULL
+ */
+static char *
+xmlPosixStrdup(const char *cur) {
+ return((char*) xmlCharStrdup(cur));
+}
/**
* xmlMemStrdup:
* @str: a zero terminated string
*
* Returns the copy of the string or NULL in case of error
*/
-xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
+xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
#endif /* DEBUG_MEMORY_LOCATION || DEBUG_MEMORY */
#include <libxml/threads.h>
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
#include <libxml/xmlerror.h>
-#include <libxml/SAX.h>
#include <libxml/SAX2.h>
#include <libxml/xmlmemory.h>
*
* Create a new xmlHashTablePtr.
*
- * Returns the newly created object, or NULL if an error occured.
+ * Returns the newly created object, or NULL if an error occurred.
*/
xmlHashTablePtr
xmlHashCreate(int size) {
*
* Create a new xmlHashTablePtr which will use @dict as the internal dictionary
*
- * Returns the newly created object, or NULL if an error occured.
+ * Returns the newly created object, or NULL if an error occurred.
*/
xmlHashTablePtr
xmlHashCreateDict(int size, xmlDictPtr dict) {
xmlFree(table);
}
+/**
+ * xmlHashDefaultDeallocator:
+ * @entry: the hash table entry
+ * @name: the entry's name
+ *
+ * Free a hash table entry with xmlFree.
+ */
+void
+xmlHashDefaultDeallocator(void *entry, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFree(entry);
+}
+
/**
* xmlHashAddEntry:
* @table: the hash table
xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
const xmlChar *name2, const xmlChar *name3,
xmlHashScanner f, void *data) {
- xmlHashScanFull3 (table, name, name2, name3,
- (xmlHashScannerFull) f, data);
+ stubData stubdata;
+ stubdata.data = data;
+ stubdata.hashscanner = f;
+ xmlHashScanFull3(table, name, name2, name3, stubHashScannerFull,
+ &stubdata);
}
/**
*
* Callback to free data from a hash.
*/
-typedef void (*xmlHashDeallocator)(void *payload, xmlChar *name);
+typedef void (*xmlHashDeallocator)(void *payload, const xmlChar *name);
/**
* xmlHashCopier:
* @payload: the data in the hash
*
* Returns a copy of the data or NULL in case of error.
*/
-typedef void *(*xmlHashCopier)(void *payload, xmlChar *name);
+typedef void *(*xmlHashCopier)(void *payload, const xmlChar *name);
/**
* xmlHashScanner:
* @payload: the data in the hash
*
* Callback when scanning data in a hash with the simple scanner.
*/
-typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name);
+typedef void (*xmlHashScanner)(void *payload, void *data, const xmlChar *name);
/**
* xmlHashScannerFull:
* @payload: the data in the hash
XMLPUBFUN void XMLCALL
xmlHashFree (xmlHashTablePtr table,
xmlHashDeallocator f);
+XMLPUBFUN void XMLCALL
+ xmlHashDefaultDeallocator(void *entry,
+ const xmlChar *name);
/*
* Add a new entry to the hash table.
#ifndef __XML_LIBXML_H__
#define __XML_LIBXML_H__
+#include <libxml/xmlstring.h>
+
#ifndef NO_LARGEFILE_SOURCE
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
#include "trio.h"
#endif
+#if defined(__clang__) || \
+ (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
+#define XML_IGNORE_PEDANTIC_WARNINGS \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
+#define XML_POP_WARNINGS \
+ _Pragma("GCC diagnostic pop")
+#else
+#define XML_IGNORE_PEDANTIC_WARNINGS
+#define XML_POP_WARNINGS
+#endif
+
/*
* Internal variable indicating if a callback has been registered for
* node creation/destruction. It avoids spending a lot of time in locking
* internal error reporting routines, shared but not partof the API.
*/
void __xmlIOErr(int domain, int code, const char *extra);
-void __xmlLoaderErr(void *ctx, const char *msg, const char *filename);
+void __xmlLoaderErr(void *ctx, const char *msg, const char *filename) LIBXML_ATTR_FORMAT(2,0);
#ifdef LIBXML_HTML_ENABLED
/*
* internal function of HTML parser needed for xmlParseInNodeContext
int __xmlRandom(void);
#endif
-int xmlNop(void);
+XMLPUBFUN xmlChar * XMLCALL xmlEscapeFormatString(xmlChar **msg);
+int xmlInputReadCallbackNop(void *context, char *buffer, int len);
#ifdef IN_LIBXML
#ifdef __GNUC__
#ifdef PIC
-#ifdef linux
+#ifdef __linux__
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
#include "elfgcchack.h"
#endif
#endif
#endif
#endif
-#if !defined(PIC) && !defined(NOLIBTOOL)
+#if !defined(PIC) && !defined(NOLIBTOOL) && !defined(LIBXML_STATIC)
# define LIBXML_STATIC 1
#endif
#endif /* ! __XML_LIBXML_H__ */
*
* Remove the first instance associated to data in the list
*
- * Returns 1 if a deallocation occured, or 0 if not found
+ * Returns 1 if a deallocation occurred, or 0 if not found
*/
int
xmlListRemoveFirst(xmlListPtr l, void *data)
*
* Remove the last instance associated to data in the list
*
- * Returns 1 if a deallocation occured, or 0 if not found
+ * Returns 1 if a deallocation occurred, or 0 if not found
*/
int
xmlListRemoveLast(xmlListPtr l, void *data)
* apply the walker function to it
*/
void
-xmlListWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
+xmlListWalk(xmlListPtr l, xmlListWalker walker, void *user) {
xmlLinkPtr lk;
if ((l == NULL) || (walker == NULL))
* apply the walker function to it
*/
void
-xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, const void *user) {
+xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, void *user) {
xmlLinkPtr lk;
if ((l == NULL) || (walker == NULL))
*
* Returns 0 to stop walking the list, 1 otherwise.
*/
-typedef int (*xmlListWalker) (const void *data, const void *user);
+typedef int (*xmlListWalker) (const void *data, void *user);
/* Creation/Deletion */
XMLPUBFUN xmlListPtr XMLCALL
XMLPUBFUN void XMLCALL
xmlListWalk (xmlListPtr l,
xmlListWalker walker,
- const void *user);
+ void *user);
XMLPUBFUN void XMLCALL
xmlListReverseWalk (xmlListPtr l,
xmlListWalker walker,
- const void *user);
+ void *user);
XMLPUBFUN void XMLCALL
xmlListMerge (xmlListPtr l1,
xmlListPtr l2);
#define HAVE_NETINET_IN_H
#define HAVE_NETDB_H
#define HAVE_SYS_TIME_H
-#else /* TESTING */
-#define NEED_SOCKETS
#endif /* TESTING */
#define IN_LIBXML
#endif
-#if defined(__MINGW32__) || defined(_WIN32_WCE)
-#ifndef _WINSOCKAPI_
-#define _WINSOCKAPI_
-#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <wsockcompat.h>
-#include <winsock2.h>
-#undef XML_SOCKLEN_T
-#define XML_SOCKLEN_T unsigned int
#endif
/**
if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
if (ctxt->path != NULL) xmlFree(ctxt->path);
+ if (ctxt->user != NULL) xmlFree(ctxt->user);
+ if (ctxt->passwd != NULL) xmlFree(ctxt->passwd);
ctxt->passive = 1;
if (ctxt->controlFd != INVALID_SOCKET) closesocket(ctxt->controlFd);
ctxt->controlFd = INVALID_SOCKET;
__xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
return (-1);
}
- if (tmp->ai_addrlen > sizeof(ctxt->ftpAddr)) {
+ if ((size_t)tmp->ai_addrlen > sizeof(ctxt->ftpAddr)) {
if (result)
freeaddrinfo (result);
__xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch");
case 2:
if (proxyPasswd == NULL)
break;
+ /* Falls through. */
case 3:
if (proxyPasswd != NULL)
snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd);
ctxt->controlFd = INVALID_SOCKET;
return(-1);
}
+ /* Falls through. */
case 2:
/* USER user@host command */
if (ctxt->user == NULL)
ctxt->controlFd = INVALID_SOCKET;
return(-1);
}
+ /* Falls through. */
case 3:
/*
* If you need support for other Proxy authentication scheme
case 3:
__xmlIOErr(XML_FROM_FTP, XML_FTP_ACCNT,
"FTP server asking for ACCNT on anonymous\n");
+ /* Falls through. */
case 1:
case 4:
case 5:
#ifdef LIBXML_FTP_ENABLED
/* Needed for portability to Windows 64 bits */
-#if defined(__MINGW32__) || defined(_WIN32_WCE)
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <winsock2.h>
#else
/**
* daniel@veillard.com
*/
-#define NEED_SOCKETS
#define IN_LIBXML
#include "libxml.h"
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
#define XML_SOCKLEN_T unsigned int
#endif
-#if defined(__MINGW32__) || defined(_WIN32_WCE)
-#ifndef _WINSOCKAPI_
-#define _WINSOCKAPI_
-#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <wsockcompat.h>
-#include <winsock2.h>
-#undef XML_SOCKLEN_T
-#define XML_SOCKLEN_T unsigned int
#endif
#include <libxml/globals.h>
char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */
char *encoding; /* encoding extracted from the contentType */
char *mimeType; /* Mime-Type extracted from the contentType */
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
z_stream *strm; /* Zlib stream object */
int usesGzip; /* "Content-Encoding: gzip" was detected */
#endif
*/
static int socket_errno(void) {
#ifdef _WINSOCKAPI_
- return(WSAGetLastError());
+ int err = WSAGetLastError();
+ switch(err) {
+ case WSAECONNRESET:
+ return(ECONNRESET);
+ case WSAEINPROGRESS:
+ return(EINPROGRESS);
+ case WSAEINTR:
+ return(EINTR);
+ case WSAESHUTDOWN:
+ return(ESHUTDOWN);
+ case WSAEWOULDBLOCK:
+ return(EWOULDBLOCK);
+ default:
+ return(err);
+ }
#else
return(errno);
#endif
if (ctxt->mimeType != NULL) xmlFree(ctxt->mimeType);
if (ctxt->location != NULL) xmlFree(ctxt->location);
if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader);
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if (ctxt->strm != NULL) {
inflateEnd(ctxt->strm);
xmlFree(ctxt->strm);
if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1)
#if defined(EINTR)
- && (errno != EINTR)
+ && (socket_errno() != EINTR)
#endif
)
return (0);
if (ctxt->authHeader != NULL)
xmlFree(ctxt->authHeader);
ctxt->authHeader = xmlMemStrdup(cur);
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
} else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Encoding:", 17) ) {
cur += 17;
while ((*cur == ' ') || (*cur == '\t')) cur++;
static SOCKET
xmlNanoHTTPConnectHost(const char *host, int port)
{
- struct hostent *h;
struct sockaddr *addr = NULL;
- struct in_addr ia;
struct sockaddr_in sockin;
#ifdef SUPPORT_IP6
struct in6_addr ia6;
struct sockaddr_in6 sockin6;
#endif
- int i;
SOCKET s;
memset (&sockin, 0, sizeof(sockin));
for (res = result; res; res = res->ai_next) {
if (res->ai_family == AF_INET) {
- if (res->ai_addrlen > sizeof(sockin)) {
+ if ((size_t)res->ai_addrlen > sizeof(sockin)) {
__xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
freeaddrinfo (result);
return INVALID_SOCKET;
addr = (struct sockaddr *)&sockin;
#ifdef SUPPORT_IP6
} else if (have_ipv6 () && (res->ai_family == AF_INET6)) {
- if (res->ai_addrlen > sizeof(sockin6)) {
+ if ((size_t)res->ai_addrlen > sizeof(sockin6)) {
__xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
freeaddrinfo (result);
return INVALID_SOCKET;
#endif
#if !defined(HAVE_GETADDRINFO) || !defined(_WIN32)
{
+ struct hostent *h;
+ struct in_addr ia;
+ int i;
+
h = gethostbyname (GETHOSTBYNAME_ARG_CAST host);
if (h == NULL) {
* extraction code. it work on Linux, if it work on your platform
* and one want to enable it, send me the defined(foobar) needed
*/
-#if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(linux)
+#if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(__linux__)
const char *h_err_txt = "";
switch (h_errno) {
int
xmlNanoHTTPRead(void *ctx, void *dest, int len) {
xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
int bytes_read = 0;
int orig_avail_in;
int z_ret;
if (dest == NULL) return(-1);
if (len <= 0) return(0);
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if (ctxt->usesGzip == 1) {
if (ctxt->strm == NULL) return(0);
/* 1 for '?' */
blen += strlen(ctxt->query) + 1;
blen += strlen(method) + strlen(ctxt->path) + 24;
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
/* reserve for possible 'Accept-Encoding: gzip' string */
blen += 23;
#endif
if (ctxt->port != 80) {
/* reserve space for ':xxxxx', incl. potential proxy */
if (proxy)
- blen += 12;
+ blen += 17;
else
- blen += 6;
+ blen += 11;
}
bp = (char*)xmlMallocAtomic(blen);
if ( bp == NULL ) {
ctxt->hostname, ctxt->port);
}
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
p += snprintf(p, blen - (p - bp), "Accept-Encoding: gzip\r\n");
#endif
xmlGenericError(xmlGenericErrorContext,
"\nRedirect to: %s\n", ctxt->location);
#endif
- while ( xmlNanoHTTPRecv(ctxt) > 0 ) ;
+ while ( xmlNanoHTTPRecv(ctxt) > 0 )
+ ;
if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
nbRedirects++;
if (redirURL != NULL)
* daniel@veillard.com
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
-#if defined(WIN32) && !defined (__CYGWIN__)
+#if defined(_WIN32) && !defined (__CYGWIN__)
#define XML_DIR_SEP '\\'
#else
#define XML_DIR_SEP '/'
#include <limits.h>
#include <string.h>
#include <stdarg.h>
+#include <stddef.h>
#include <libxml/xmlmemory.h>
#include <libxml/threads.h>
#include <libxml/globals.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
#include "buf.h"
#include "enc.h"
* entities problems
*/
if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
- (ent->content != NULL) && (ent->checked == 0)) {
+ (ent->content != NULL) && (ent->checked == 0) &&
+ (ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
unsigned long oldnbent = ctxt->nbentities;
xmlChar *rep;
ent->checked = 1;
+ ++ctxt->depth;
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0, 0);
+ --ctxt->depth;
+ if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
+ ent->content[0] = 0;
+ }
ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
if (rep != NULL) {
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
{
const char *errmsg;
- char errstr[129] = "";
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
default:
errmsg = "Unregistered error message";
}
- if (info == NULL)
- snprintf(errstr, 128, "%s\n", errmsg);
- else
- snprintf(errstr, 128, "%s: %%s\n", errmsg);
if (ctxt != NULL)
ctxt->errNo = error;
- __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
- XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
- info);
+ if (info == NULL) {
+ __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+ XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
+ errmsg);
+ } else {
+ __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+ XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
+ errmsg, info);
+ }
if (ctxt != NULL) {
ctxt->wellFormed = 0;
if (ctxt->recovery == 0)
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg)
{
*
* Handle a warning.
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
*
* Handle a validity error.
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, const xmlChar *str2)
{
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, int val)
{
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, int val,
const xmlChar *str2)
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar * val)
{
*
* Handle a non fatal parser error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar * val)
{
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg,
const xmlChar * info1, const xmlChar * info2,
*
* Handle a namespace warning error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg,
const xmlChar * info1, const xmlChar * info2,
struct _xmlDefAttrs {
int nbAttrs; /* number of defaulted attributes on that element */
int maxAttrs; /* the size of the array */
- const xmlChar *values[5]; /* array of localname/prefix/values/external */
+#if __STDC_VERSION__ >= 199901L
+ /* Using a C99 flexible array member avoids UBSan errors. */
+ const xmlChar *values[]; /* array of localname/prefix/values/external */
+#else
+ const xmlChar *values[5];
+#endif
};
/**
return;
xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
- (void *) (long) type);
+ (void *) (ptrdiff_t) type);
return;
mem_error:
const xmlChar *unused ATTRIBUTE_UNUSED) {
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
- if (((long) payload) == XML_ATTRIBUTE_CDATA) {
+ if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
}
}
ctxt->name = value;
ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
- ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
+ ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (ptrdiff_t) nsNr;
return (ctxt->nameNr++);
mem_error:
xmlErrMemory(ctxt, NULL);
#define CUR (*ctxt->input->cur)
#define NXT(val) ctxt->input->cur[(val)]
#define CUR_PTR ctxt->input->cur
+#define BASE_PTR ctxt->input->base
#define CMP4( s, c1, c2, c3, c4 ) \
( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
#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, INPUT_CHUNK) <= 0)) \
- xmlPopInput(ctxt); \
+ if (*ctxt->input->cur == 0) \
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
} while (0)
#define SKIPL(val) do { \
ctxt->nbChars++; \
ctxt->input->cur++; \
} \
- if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
- if ((*ctxt->input->cur == 0) && \
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
- xmlPopInput(ctxt); \
+ if (*ctxt->input->cur == 0) \
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
} while (0)
#define SHRINK if ((ctxt->progressive == 0) && \
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
xmlParserInputShrink(ctxt->input);
- if ((*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
- xmlPopInput(ctxt);
- }
+ if (*ctxt->input->cur == 0)
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+}
#define GROW if ((ctxt->progressive == 0) && \
(ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
if (((curEnd > (unsigned long) XML_MAX_LOOKUP_LIMIT) ||
(curBase > (unsigned long) XML_MAX_LOOKUP_LIMIT)) &&
- ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
+ ((ctxt->input->buf) &&
+ (ctxt->input->buf->readcallback != xmlInputReadCallbackNop)) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
xmlHaltParser(ctxt);
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
return;
}
- if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
- xmlPopInput(ctxt);
+ if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
}
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
ctxt->input->line++; ctxt->input->col = 1; \
} else ctxt->input->col++; \
ctxt->input->cur += l; \
- if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
} while (0)
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
}
ctxt->input->cur = cur;
} else {
- int cur;
- do {
- cur = CUR;
- while ((IS_BLANK_CH(cur) && /* CHECKED tstblanks.xml */
- (ctxt->instate != XML_PARSER_EOF))) {
+ int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
+
+ while (1) {
+ if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
NEXT;
- cur = CUR;
- res++;
- }
- while ((cur == 0) && (ctxt->inputNr > 1) &&
- (ctxt->instate != XML_PARSER_COMMENT)) {
- xmlPopInput(ctxt);
- cur = CUR;
- }
- /*
- * Need to handle support of entities branching here
- */
- if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
- } while ((IS_BLANK(cur)) && /* CHECKED tstblanks.xml */
- (ctxt->instate != XML_PARSER_EOF));
+ } else if (CUR == '%') {
+ /*
+ * Need to handle support of entities branching here
+ */
+ if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
+ break;
+ xmlParsePEReference(ctxt);
+ } else if (CUR == 0) {
+ if (ctxt->inputNr <= 1)
+ break;
+ xmlPopInput(ctxt);
+ } else {
+ break;
+ }
+
+ /*
+ * Also increase the counter when entering or exiting a PERef.
+ * The spec says: "When a parameter-entity reference is recognized
+ * in the DTD and included, its replacement text MUST be enlarged
+ * by the attachment of one leading and one following space (#x20)
+ * character."
+ */
+ res++;
+ }
}
return(res);
}
if (xmlParserDebugEntities)
xmlGenericError(xmlGenericErrorContext,
"Popping input %d\n", ctxt->inputNr);
+ if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
+ (ctxt->instate != XML_PARSER_EOF))
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "Unfinished entity outside the DTD");
xmlFreeInputStream(inputPop(ctxt));
- if ((*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
- return(xmlPopInput(ctxt));
+ if (*ctxt->input->cur == 0)
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
return(CUR);
}
xmlGenericError(xmlGenericErrorContext,
"Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
}
+ if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
+ (ctxt->inputNr > 1024)) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ while (ctxt->inputNr > 1)
+ xmlFreeInputStream(inputPop(ctxt));
+ return(-1);
+ }
ret = inputPush(ctxt, input);
if (ctxt->instate == XML_PARSER_EOF)
return(-1);
return(0);
}
-/**
- * xmlNewBlanksWrapperInputStream:
- * @ctxt: an XML parser context
- * @entity: an Entity pointer
- *
- * Create a new input stream for wrapping
- * blanks around a PEReference
- *
- * Returns the new input stream or NULL
- */
-
-static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
-
-static xmlParserInputPtr
-xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
- xmlParserInputPtr input;
- xmlChar *buffer;
- size_t length;
- if (entity == NULL) {
- xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "xmlNewBlanksWrapperInputStream entity\n");
- return(NULL);
- }
- if (xmlParserDebugEntities)
- xmlGenericError(xmlGenericErrorContext,
- "new blanks wrapper for entity: %s\n", entity->name);
- input = xmlNewInputStream(ctxt);
- if (input == NULL) {
- return(NULL);
- }
- length = xmlStrlen(entity->name) + 5;
- buffer = xmlMallocAtomic(length);
- if (buffer == NULL) {
- xmlErrMemory(ctxt, NULL);
- xmlFree(input);
- return(NULL);
- }
- buffer [0] = ' ';
- buffer [1] = '%';
- buffer [length-3] = ';';
- buffer [length-2] = ' ';
- buffer [length-1] = 0;
- memcpy(buffer + 2, entity->name, length - 5);
- input->free = deallocblankswrapper;
- input->base = buffer;
- input->cur = buffer;
- input->length = length;
- input->end = &buffer[length];
- return(input);
-}
-
/**
* xmlParserHandlePEReference:
* @ctxt: the parser context
*/
void
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
- const xmlChar *name;
- xmlEntityPtr entity = NULL;
- xmlParserInputPtr input;
-
- if (RAW != '%') return;
switch(ctxt->instate) {
case XML_PARSER_CDATA_SECTION:
return;
return;
}
- NEXT;
- name = xmlParseName(ctxt);
- if (xmlParserDebugEntities)
- xmlGenericError(xmlGenericErrorContext,
- "PEReference: %s\n", name);
- if (name == NULL) {
- xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
- } else {
- if (RAW == ';') {
- NEXT;
- if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
- entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
- if (ctxt->instate == XML_PARSER_EOF)
- return;
- if (entity == NULL) {
-
- /*
- * [ WFC: Entity Declared ]
- * In a document without any DTD, a document with only an
- * internal DTD subset which contains no parameter entity
- * references, or a document with "standalone='yes'", ...
- * ... The declaration of a parameter entity must precede
- * any reference to it...
- */
- if ((ctxt->standalone == 1) ||
- ((ctxt->hasExternalSubset == 0) &&
- (ctxt->hasPErefs == 0))) {
- xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
- "PEReference: %%%s; not found\n", name);
- } else {
- /*
- * [ VC: Entity Declared ]
- * In a document with an external subset or external
- * parameter entities with "standalone='no'", ...
- * ... The declaration of a parameter entity must precede
- * any reference to it...
- */
- if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
- xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
- "PEReference: %%%s; not found\n",
- name, NULL);
- } else
- xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
- "PEReference: %%%s; not found\n",
- name, NULL);
- ctxt->valid = 0;
- }
- xmlParserEntityCheck(ctxt, 0, NULL, 0);
- } else if (ctxt->input->free != deallocblankswrapper) {
- input = xmlNewBlanksWrapperInputStream(ctxt, entity);
- if (xmlPushInput(ctxt, input) < 0)
- return;
- } else {
- if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
- (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
- xmlChar start[4];
- xmlCharEncoding enc;
-
- /*
- * Note: external parameter entities will not be loaded, it
- * is not required for a non-validating parser, unless the
- * option of validating, or substituting entities were
- * given. Doing so is far more secure as the parser will
- * only process data coming from the document entity by
- * default.
- */
- if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
- ((ctxt->options & XML_PARSE_NOENT) == 0) &&
- ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
- ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
- ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
- (ctxt->replaceEntities == 0) &&
- (ctxt->validate == 0))
- return;
-
- /*
- * handle the extra spaces added before and after
- * c.f. http://www.w3.org/TR/REC-xml#as-PE
- * this is done independently.
- */
- input = xmlNewEntityInputStream(ctxt, entity);
- if (xmlPushInput(ctxt, input) < 0)
- return;
-
- /*
- * Get the 4 first bytes and decode the charset
- * if enc != XML_CHAR_ENCODING_NONE
- * plug some encoding conversion routines.
- * Note that, since we may have some non-UTF8
- * encoding (like UTF16, bug 135229), the 'length'
- * is not known, but we can calculate based upon
- * the amount of data in the buffer.
- */
- GROW
- if (ctxt->instate == XML_PARSER_EOF)
- return;
- if ((ctxt->input->end - ctxt->input->cur)>=4) {
- start[0] = RAW;
- start[1] = NXT(1);
- start[2] = NXT(2);
- start[3] = NXT(3);
- enc = xmlDetectCharEncoding(start, 4);
- if (enc != XML_CHAR_ENCODING_NONE) {
- xmlSwitchEncoding(ctxt, enc);
- }
- }
-
- if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
- (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
- (IS_BLANK_CH(NXT(5)))) {
- xmlParseTextDecl(ctxt);
- }
- } else {
- xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
- "PEReference: %s is not a parameter entity\n",
- name);
- }
- }
- } else {
- xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
- }
- }
+ xmlParsePEReference(ctxt);
}
/*
if (c == 0) break;
if ((c == '&') && (str[1] == '#')) {
int val = xmlParseStringCharRef(ctxt, &str);
- if (val != 0) {
- COPY_BUF(0,buffer,nbchars,val);
- }
+ if (val == 0)
+ goto int_error;
+ COPY_BUF(0,buffer,nbchars,val);
if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
"String decoding Entity Reference: %.30s\n",
str);
ent = xmlParseStringEntityRef(ctxt, &str);
- if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
- (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
- goto int_error;
xmlParserEntityCheck(ctxt, 0, ent, 0);
if (ent != NULL)
ctxt->nbentities += ent->checked / 2;
} else {
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
"predefined entity has no content\n");
+ goto int_error;
}
} else if ((ent != NULL) && (ent->content != NULL)) {
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
-
- if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
- (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
- goto int_error;
-
- if (rep != NULL) {
- current = rep;
- while (*current != 0) { /* non input consuming loop */
- buffer[nbchars++] = *current++;
- if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
- if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
- goto int_error;
- growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
- }
- }
- xmlFree(rep);
- rep = NULL;
- }
+ if (rep == NULL)
+ goto int_error;
+
+ current = rep;
+ while (*current != 0) { /* non input consuming loop */
+ buffer[nbchars++] = *current++;
+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+ if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
+ goto int_error;
+ growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+ }
+ }
+ xmlFree(rep);
+ rep = NULL;
} else if (ent != NULL) {
int i = xmlStrlen(ent->name);
const xmlChar *cur = ent->name;
xmlGenericError(xmlGenericErrorContext,
"String decoding PE Reference: %.30s\n", str);
ent = xmlParseStringPEReference(ctxt, &str);
- if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
- goto int_error;
xmlParserEntityCheck(ctxt, 0, ent, 0);
if (ent != NULL)
ctxt->nbentities += ent->checked / 2;
if (ent != NULL) {
if (ent->content == NULL) {
- xmlLoadEntityContent(ctxt, ent);
+ /*
+ * Note: external parsed entities will not be loaded,
+ * it is not required for a non-validating parser to
+ * complete external PEreferences coming from the
+ * internal subset
+ */
+ if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
+ ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
+ (ctxt->validate != 0)) {
+ xmlLoadEntityContent(ctxt, ent);
+ } else {
+ xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
+ "not validating will not read content for PE entity %s\n",
+ ent->name, NULL);
+ }
}
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
- if (rep != NULL) {
- current = rep;
- while (*current != 0) { /* non input consuming loop */
- buffer[nbchars++] = *current++;
- if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
- if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
- goto int_error;
- growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
- }
- }
- xmlFree(rep);
- rep = NULL;
- }
+ if (rep == NULL)
+ goto int_error;
+ current = rep;
+ while (*current != 0) { /* non input consuming loop */
+ buffer[nbchars++] = *current++;
+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+ if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
+ goto int_error;
+ growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+ }
+ }
+ xmlFree(rep);
+ rep = NULL;
}
} else {
COPY_BUF(l,buffer,nbchars,c);
len += l;
NEXTL(l);
c = CUR_CHAR(l);
- if (c == 0) {
- count = 0;
- GROW;
- if (ctxt->instate == XML_PARSER_EOF)
- return(NULL);
- c = CUR_CHAR(l);
- }
}
}
if ((len > XML_MAX_NAME_LENGTH) &&
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
return(NULL);
}
+ if (ctxt->input->cur - ctxt->input->base < len) {
+ /*
+ * There were a couple of bugs where PERefs lead to to a change
+ * of the buffer. Check the buffer size to avoid passing an invalid
+ * pointer to xmlDictLookup.
+ */
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "unexpected change of input buffer");
+ return (NULL);
+ }
if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
int len = 0, l;
int c;
int count = 0;
- const xmlChar *end; /* needed because CUR_CHAR() can move cur on \r\n */
+ size_t startPosition = 0;
#ifdef DEBUG
nbParseNCNameComplex++;
* Handler for more complex cases
*/
GROW;
- end = ctxt->input->cur;
+ startPosition = CUR_PTR - BASE_PTR;
c = CUR_CHAR(l);
if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
(!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
}
len += l;
NEXTL(l);
- end = ctxt->input->cur;
c = CUR_CHAR(l);
if (c == 0) {
count = 0;
*/
ctxt->input->cur -= l;
GROW;
- ctxt->input->cur += l;
if (ctxt->instate == XML_PARSER_EOF)
return(NULL);
- end = ctxt->input->cur;
+ ctxt->input->cur += l;
c = CUR_CHAR(l);
}
}
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
return(NULL);
}
- return(xmlDictLookup(ctxt->dict, end - len, len));
+ return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
}
/**
}
/* failure (or end of input buffer), check with full function */
ret = xmlParseName (ctxt);
- /* strings coming from the dictionnary direct compare possible */
+ /* strings coming from the dictionary direct compare possible */
if (ret == other) {
return (const xmlChar*) 1;
}
ctxt->instate = XML_PARSER_ENTITY_VALUE;
input = ctxt->input;
GROW;
- if (ctxt->instate == XML_PARSER_EOF) {
- xmlFree(buf);
- return(NULL);
- }
+ if (ctxt->instate == XML_PARSER_EOF)
+ goto error;
NEXT;
c = CUR_CHAR(l);
/*
tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (tmp == NULL) {
xmlErrMemory(ctxt, NULL);
- xmlFree(buf);
- return(NULL);
+ goto error;
}
buf = tmp;
}
COPY_BUF(l,buf,len,c);
NEXTL(l);
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
- xmlPopInput(ctxt);
GROW;
c = CUR_CHAR(l);
}
}
buf[len] = 0;
- if (ctxt->instate == XML_PARSER_EOF) {
- xmlFree(buf);
- return(NULL);
+ if (ctxt->instate == XML_PARSER_EOF)
+ goto error;
+ if (c != stop) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
+ goto error;
}
+ NEXT;
/*
* Raise problem w.r.t. '&' and '%' being used in non-entities
if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
xmlChar *name;
xmlChar tmp = *cur;
+ int nameOk = 0;
cur++;
name = xmlParseStringName(ctxt, &cur);
- if ((name == NULL) || (*cur != ';')) {
+ if (name != NULL) {
+ nameOk = 1;
+ xmlFree(name);
+ }
+ if ((nameOk == 0) || (*cur != ';')) {
xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
"EntityValue: '%c' forbidden except for entities references\n",
tmp);
+ goto error;
}
if ((tmp == '%') && (ctxt->inSubset == 1) &&
(ctxt->inputNr == 1)) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
+ goto error;
}
- if (name != NULL)
- xmlFree(name);
if (*cur == 0)
break;
}
/*
* Then PEReference entities are substituted.
+ *
+ * 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 here.
*/
- if (c != stop) {
- xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
- xmlFree(buf);
- } 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 here.
- */
- ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
- 0, 0, 0);
- if (orig != NULL)
- *orig = buf;
- else
- xmlFree(buf);
+ ++ctxt->depth;
+ ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
+ 0, 0, 0);
+ --ctxt->depth;
+ if (orig != NULL) {
+ *orig = buf;
+ buf = NULL;
}
+error:
+ if (buf != NULL)
+ xmlFree(buf);
return(ret);
}
} else if ((ent != NULL) &&
(ctxt->replaceEntities != 0)) {
if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
+ ++ctxt->depth;
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF,
0, 0, 0);
+ --ctxt->depth;
if (rep != NULL) {
current = rep;
while (*current != 0) { /* non input consuming */
(ent->content != NULL) && (ent->checked == 0)) {
unsigned long oldnbent = ctxt->nbentities;
+ ++ctxt->depth;
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0, 0);
+ --ctxt->depth;
ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
if (rep != NULL) {
ent->checked |= 1;
xmlFree(rep);
rep = NULL;
- }
+ } else {
+ ent->content[0] = 0;
+ }
}
/*
if (*in == ']') {
if ((in[1] == ']') && (in[2] == '>')) {
xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
- ctxt->input->cur = in;
+ ctxt->input->cur = in + 1;
return;
}
in++;
*publicID = NULL;
if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
SKIP(6);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'SYSTEM'\n");
}
- SKIP_BLANKS;
URI = xmlParseSystemLiteral(ctxt);
if (URI == NULL) {
xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
}
} else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
SKIP(6);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'PUBLIC'\n");
}
- SKIP_BLANKS;
*publicID = xmlParsePubidLiteral(ctxt);
if (*publicID == NULL) {
xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
/*
* We don't handle [83] so "S SystemLiteral" is required.
*/
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the Public Identifier\n");
}
} else {
/*
* We handle [83] so we return immediately, if
- * "S SystemLiteral" is not detected. From a purely parsing
- * point of view that's a nice mess.
+ * "S SystemLiteral" is not detected. We skip blanks if no
+ * system literal was found, but this is harmless since we must
+ * be at the end of a NotationDecl.
*/
- const xmlChar *ptr;
- GROW;
-
- ptr = CUR_PTR;
- if (!IS_BLANK_CH(*ptr)) return(NULL);
-
- while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
- if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
+ if (SKIP_BLANKS == 0) return(NULL);
+ if ((CUR != '\'') && (CUR != '"')) return(NULL);
}
- SKIP_BLANKS;
URI = xmlParseSystemLiteral(ctxt);
if (URI == NULL) {
xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
} else {
if (inputid != ctxt->input->id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Comment doesn't start and stop in the same entity\n");
+ "Comment doesn't start and stop in the same"
+ " entity\n");
}
NEXT;
if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
if (in[2] == '>') {
if (ctxt->input->id != inputid) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "comment doesn't start and stop in the same entity\n");
+ "comment doesn't start and stop in the"
+ " same entity\n");
}
SKIP(3);
if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
int count = 0;
if ((RAW == '<') && (NXT(1) == '?')) {
- xmlParserInputPtr input = ctxt->input;
+ int inputid = ctxt->input->id;
state = ctxt->instate;
ctxt->instate = XML_PARSER_PI;
/*
target = xmlParsePITarget(ctxt);
if (target != NULL) {
if ((RAW == '?') && (NXT(1) == '>')) {
- if (input != ctxt->input) {
+ if (inputid != ctxt->input->id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "PI declaration doesn't start and stop in the same entity\n");
+ "PI declaration doesn't start and stop in"
+ " the same entity\n");
}
SKIP(2);
ctxt->instate = state;
return;
}
- cur = CUR;
- if (!IS_BLANK(cur)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
"ParsePI: PI %s space expected\n", target);
}
- SKIP_BLANKS;
cur = CUR_CHAR(l);
while (IS_CHAR(cur) && /* checked */
((cur != '?') || (NXT(1) != '>'))) {
xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
"ParsePI: PI %s never end ...\n", target);
} else {
- if (input != ctxt->input) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "PI declaration doesn't start and stop in the same entity\n");
+ if (inputid != ctxt->input->id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "PI declaration doesn't start and stop in"
+ " the same entity\n");
}
SKIP(2);
xmlChar *Systemid;
if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
- xmlParserInputPtr input = ctxt->input;
+ int inputid = ctxt->input->id;
SHRINK;
SKIP(10);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!NOTATION'\n");
return;
}
- SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
return;
}
- if (!IS_BLANK_CH(CUR)) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "Space required after the NOTATION name'\n");
- return;
- }
if (xmlStrchr(name, ':') != NULL) {
xmlNsErr(ctxt, XML_NS_ERR_COLON,
"colons are forbidden from notation names '%s'\n",
name, NULL, NULL);
}
- SKIP_BLANKS;
+ if (SKIP_BLANKS == 0) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the NOTATION name'\n");
+ return;
+ }
/*
* Parse the IDs.
SKIP_BLANKS;
if (RAW == '>') {
- if (input != ctxt->input) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "Notation declaration doesn't start and stop in the same entity\n");
+ if (inputid != ctxt->input->id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Notation declaration doesn't start and stop"
+ " in the same entity\n");
}
NEXT;
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
const xmlChar *ndata = NULL;
int isParameter = 0;
xmlChar *orig = NULL;
- int skipped;
/* GROW; done in the caller */
if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
- xmlParserInputPtr input = ctxt->input;
+ int inputid = ctxt->input->id;
SHRINK;
SKIP(8);
- skipped = SKIP_BLANKS;
- if (skipped == 0) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!ENTITY'\n");
}
if (RAW == '%') {
NEXT;
- skipped = SKIP_BLANKS;
- if (skipped == 0) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "Space required after '%'\n");
+ "Space required after '%%'\n");
}
isParameter = 1;
}
"colons are forbidden from entities names '%s'\n",
name, NULL, NULL);
}
- skipped = SKIP_BLANKS;
- if (skipped == 0) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the entity name\n");
}
xmlFreeURI(uri);
}
}
- if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
+ if ((RAW != '>') && (SKIP_BLANKS == 0)) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required before 'NDATA'\n");
}
- SKIP_BLANKS;
if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
SKIP(5);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'NDATA'\n");
}
- SKIP_BLANKS;
ndata = xmlParseName(ctxt);
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->unparsedEntityDecl != NULL))
}
}
if (ctxt->instate == XML_PARSER_EOF)
- return;
+ goto done;
SKIP_BLANKS;
if (RAW != '>') {
xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
"xmlParseEntityDecl: entity %s not terminated\n", name);
xmlHaltParser(ctxt);
} else {
- if (input != ctxt->input) {
+ if (inputid != ctxt->input->id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Entity declaration doesn't start and stop in the same entity\n");
+ "Entity declaration doesn't start and stop in"
+ " the same entity\n");
}
NEXT;
}
cur = xmlSAX2GetEntity(ctxt, name);
}
}
- if (cur != NULL) {
- if (cur->orig != NULL)
- xmlFree(orig);
- else
- cur->orig = orig;
- } else
- xmlFree(orig);
+ if ((cur != NULL) && (cur->orig == NULL)) {
+ cur->orig = orig;
+ orig = NULL;
+ }
}
+
+done:
if (value != NULL) xmlFree(value);
if (URI != NULL) xmlFree(URI);
if (literal != NULL) xmlFree(literal);
+ if (orig != NULL) xmlFree(orig);
}
}
if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
SKIP(6);
val = XML_ATTRIBUTE_FIXED;
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '#FIXED'\n");
}
- SKIP_BLANKS;
}
ret = xmlParseAttValue(ctxt);
ctxt->instate = XML_PARSER_DTD;
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
SKIP(8);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'NOTATION'\n");
return(0);
}
- SKIP_BLANKS;
*tree = xmlParseNotationType(ctxt);
if (*tree == NULL) return(0);
return(XML_ATTRIBUTE_NOTATION);
xmlEnumerationPtr tree;
if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
- xmlParserInputPtr input = ctxt->input;
+ int inputid = ctxt->input->id;
SKIP(9);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!ATTLIST'\n");
}
- SKIP_BLANKS;
elemName = xmlParseName(ctxt);
if (elemName == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
SKIP_BLANKS;
GROW;
while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
- const xmlChar *check = CUR_PTR;
int type;
int def;
xmlChar *defaultValue = NULL;
break;
}
GROW;
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the attribute name\n");
break;
}
- SKIP_BLANKS;
type = xmlParseAttributeType(ctxt, &tree);
if (type <= 0) {
}
GROW;
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the attribute type\n");
if (tree != NULL)
xmlFreeEnumeration(tree);
break;
}
- SKIP_BLANKS;
def = xmlParseDefaultDecl(ctxt, &defaultValue);
if (def <= 0) {
GROW;
if (RAW != '>') {
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the attribute default value\n");
if (defaultValue != NULL)
xmlFreeEnumeration(tree);
break;
}
- SKIP_BLANKS;
- }
- if (check == CUR_PTR) {
- xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "in xmlParseAttributeListDecl\n");
- if (defaultValue != NULL)
- xmlFree(defaultValue);
- if (tree != NULL)
- xmlFreeEnumeration(tree);
- break;
}
if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
(ctxt->sax->attributeDecl != NULL))
GROW;
}
if (RAW == '>') {
- if (input != ctxt->input) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Attribute list declaration doesn't start and stop in the same entity\n",
- NULL, NULL);
+ if (inputid != ctxt->input->id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Attribute list declaration doesn't start and"
+ " stop in the same entity\n");
}
NEXT;
}
SKIP_BLANKS;
SHRINK;
if (RAW == ')') {
- if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
- NULL, NULL);
+ if (ctxt->input->id != inputchk) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Element content declaration doesn't start and"
+ " stop in the same entity\n");
}
NEXT;
ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
if (elem == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParseElementMixedContentDecl : Name expected\n");
- xmlFreeDocElementContent(ctxt->myDoc, cur);
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
return(NULL);
}
SKIP_BLANKS;
}
if (ret != NULL)
ret->ocur = XML_ELEMENT_CONTENT_MULT;
- if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
- NULL, NULL);
+ if (ctxt->input->id != inputchk) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Element content declaration doesn't start and"
+ " stop in the same entity\n");
}
SKIP(2);
} else {
if (last != NULL)
last->parent = cur;
}
- if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
- NULL, NULL);
+ if (ctxt->input->id != inputchk) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Element content declaration doesn't start and stop in"
+ " the same entity\n");
}
NEXT;
if (RAW == '?') {
/* GROW; done in the caller */
if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
- xmlParserInputPtr input = ctxt->input;
+ int inputid = ctxt->input->id;
SKIP(9);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'ELEMENT'\n");
+ return(-1);
}
- SKIP_BLANKS;
name = xmlParseName(ctxt);
if (name == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParseElementDecl: no name for Element\n");
return(-1);
}
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after the element name\n");
}
- SKIP_BLANKS;
if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
SKIP(5);
/*
}
SKIP_BLANKS;
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
- SKIP_BLANKS;
if (RAW != '>') {
xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
xmlFreeDocElementContent(ctxt->myDoc, content);
}
} else {
- if (input != ctxt->input) {
+ if (inputid != ctxt->input->id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Element declaration doesn't start and stop in the same entity\n");
+ "Element declaration doesn't start and stop in"
+ " the same entity\n");
}
NEXT;
return;
} else {
if (ctxt->input->id != id) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not in the same entity\n",
- NULL, NULL);
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is not"
+ " in the same entity\n");
}
NEXT;
}
"Entering INCLUDE Conditional Section\n");
}
+ SKIP_BLANKS;
+ GROW;
while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
(NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
const xmlChar *check = CUR_PTR;
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
- } else if (IS_BLANK_CH(CUR)) {
- NEXT;
- } else if (RAW == '%') {
- xmlParsePEReference(ctxt);
} else
xmlParseMarkupDecl(ctxt);
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
+ SKIP_BLANKS;
+ GROW;
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ xmlHaltParser(ctxt);
break;
}
}
return;
} else {
if (ctxt->input->id != id) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not in the same entity\n",
- NULL, NULL);
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is not"
+ " in the same entity\n");
}
NEXT;
}
xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
} else {
if (ctxt->input->id != id) {
- xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not in the same entity\n",
- NULL, NULL);
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is not in"
+ " the same entity\n");
}
if ((ctxt-> instate != XML_PARSER_EOF) &&
((ctxt->input->cur + 3) <= ctxt->input->end))
if (ctxt->instate == XML_PARSER_EOF)
return;
- /*
- * This is only for internal subset. On external entities,
- * the replacement is done before parsing stage
- */
- if ((ctxt->external == 0) && (ctxt->inputNr == 1))
- xmlParsePEReference(ctxt);
-
/*
* Conditional sections are allowed from entities included
* by PE References in the internal subset.
return;
}
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space needed after '<?xml'\n");
}
- SKIP_BLANKS;
/*
* We may have the VersionInfo here.
if (version == NULL)
version = xmlCharStrdup(XML_DEFAULT_VERSION);
else {
- if (!IS_BLANK_CH(CUR)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space needed here\n");
}
ctxt->instate = XML_PARSER_DTD;
ctxt->external = 1;
+ SKIP_BLANKS;
while (((RAW == '<') && (NXT(1) == '?')) ||
((RAW == '<') && (NXT(1) == '!')) ||
- (RAW == '%') || IS_BLANK_CH(CUR)) {
+ (RAW == '%')) {
const xmlChar *check = CUR_PTR;
unsigned int cons = ctxt->input->consumed;
GROW;
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
- } else if (IS_BLANK_CH(CUR)) {
- NEXT;
- } else if (RAW == '%') {
- xmlParsePEReference(ctxt);
} else
xmlParseMarkupDecl(ctxt);
-
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
+ SKIP_BLANKS;
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
(ret != XML_WAR_UNDECLARED_ENTITY)) {
xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
"Entity '%s' failed to parse\n", ent->name);
+ if (ent->content != NULL)
+ ent->content[0] = 0;
xmlParserEntityCheck(ctxt, 0, ent, 0);
} else if (list != NULL) {
xmlFreeNodeList(list);
}
if (ent->checked == 0)
ent->checked = 2;
+
+ /* Prevent entity from being parsed and expanded twice (Bug 760367). */
+ was_checked = 0;
} else if (ent->checked != 1) {
ctxt->nbentities += ent->checked / 2;
}
NEXT;
name = xmlParseName(ctxt);
if (name == NULL) {
- xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
- "xmlParsePEReference: no name\n");
+ xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
return;
}
+ if (xmlParserDebugEntities)
+ xmlGenericError(xmlGenericErrorContext,
+ "PEReference: %s\n", name);
if (RAW != ';') {
- xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+ xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
return;
}
* ... The declaration of a parameter entity must
* precede any reference to it...
*/
- xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
- "PEReference: %%%s; not found\n",
- name, NULL);
- ctxt->valid = 0;
+ if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
+ xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "PEReference: %%%s; not found\n",
+ name, NULL);
+ } else
+ xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "PEReference: %%%s; not found\n",
+ name, NULL);
+ ctxt->valid = 0;
}
xmlParserEntityCheck(ctxt, 0, NULL, 0);
} else {
xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
"Internal: %%%s; is not a parameter entity\n",
name, NULL);
- } else if (ctxt->input->free != deallocblankswrapper) {
- input = xmlNewBlanksWrapperInputStream(ctxt, entity);
- if (xmlPushInput(ctxt, input) < 0)
- return;
} else {
- /*
- * TODO !!!
- * handle the extra spaces added before and after
- * c.f. http://www.w3.org/TR/REC-xml#as-PE
- */
+ xmlChar start[4];
+ xmlCharEncoding enc;
+
+ if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
+ ((ctxt->options & XML_PARSE_NOENT) == 0) &&
+ ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
+ ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
+ ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
+ (ctxt->replaceEntities == 0) &&
+ (ctxt->validate == 0))
+ return;
+
input = xmlNewEntityInputStream(ctxt, entity);
- if (xmlPushInput(ctxt, input) < 0)
+ if (xmlPushInput(ctxt, input) < 0) {
+ xmlFreeInputStream(input);
return;
- if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
- (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
- (IS_BLANK_CH(NXT(5)))) {
- xmlParseTextDecl(ctxt);
- if (ctxt->errNo ==
- XML_ERR_UNSUPPORTED_ENCODING) {
- /*
- * The XML REC instructs us to stop parsing
- * right here
- */
- xmlHaltParser(ctxt);
- return;
- }
- }
+ }
+
+ if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ * Note that, since we may have some non-UTF8
+ * encoding (like UTF16, bug 135229), the 'length'
+ * is not known, but we can calculate based upon
+ * the amount of data in the buffer.
+ */
+ GROW
+ if (ctxt->instate == XML_PARSER_EOF)
+ return;
+ if ((ctxt->input->end - ctxt->input->cur)>=4) {
+ start[0] = RAW;
+ start[1] = NXT(1);
+ start[2] = NXT(2);
+ start[3] = NXT(3);
+ enc = xmlDetectCharEncoding(start, 4);
+ if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+ }
+
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
+ (IS_BLANK_CH(NXT(5)))) {
+ xmlParseTextDecl(ctxt);
+ }
+ }
}
}
ctxt->hasPErefs = 1;
entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
if (ctxt->instate == XML_PARSER_EOF) {
xmlFree(name);
+ *str = ptr;
return(NULL);
}
if (entity == NULL) {
* Is there any DTD definition ?
*/
if (RAW == '[') {
+ int baseInputNr = ctxt->inputNr;
ctxt->instate = XML_PARSER_DTD;
NEXT;
/*
* PEReferences.
* Subsequence (markupdecl | PEReference | S)*
*/
- while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
+ while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
+ (ctxt->instate != XML_PARSER_EOF)) {
const xmlChar *check = CUR_PTR;
unsigned int cons = ctxt->input->consumed;
xmlParseMarkupDecl(ctxt);
xmlParsePEReference(ctxt);
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
-
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlParseInternalSubset: error detected in Markup declaration\n");
- break;
+ if (ctxt->inputNr > baseInputNr)
+ xmlPopInput(ctxt);
+ else
+ break;
}
}
if (RAW == ']') {
*/
if (RAW != '>') {
xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+ return;
}
NEXT;
}
ctxt->instate = XML_PARSER_CONTENT;
} else {
xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
- "Specification mandate value for attribute %s\n", name);
+ "Specification mandates value for attribute %s\n", name);
return(NULL);
}
GROW
if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
break;
- if (!IS_BLANK_CH(RAW)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"attributes construct error\n");
}
- SKIP_BLANKS;
if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
(attname == NULL) && (attvalue == NULL)) {
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
* @prefix: the prefix to lookup
*
* Lookup the namespace name for the @prefix (which ca be NULL)
- * The prefix must come from the @ctxt->dict dictionnary
+ * The prefix must come from the @ctxt->dict dictionary
*
* Returns the namespace name or NULL if not bound
*/
if (ctxt->attsSpecial != NULL) {
int type;
- type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
- pref, elem, *prefix, name);
+ type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
+ pref, elem, *prefix, name);
if (type != 0)
normalize = 1;
}
ctxt->instate = XML_PARSER_CONTENT;
} else {
xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
- "Specification mandate value for attribute %s\n",
+ "Specification mandates value for attribute %s\n",
name);
return (NULL);
}
xmlChar *attvalue;
const xmlChar **atts = ctxt->atts;
int maxatts = ctxt->maxatts;
- int nratts, nbatts, nbdef;
- int i, j, nbNs, attval, oldline, oldcol, inputNr;
- const xmlChar *base;
+ int nratts, nbatts, nbdef, inputid;
+ int i, j, nbNs, attval;
unsigned long cur;
int nsNr = ctxt->nsNr;
* The Shrinking is only possible once the full set of attribute
* callbacks have been done.
*/
-reparse:
SHRINK;
- base = ctxt->input->base;
cur = ctxt->input->cur - ctxt->input->base;
- inputNr = ctxt->inputNr;
- oldline = ctxt->input->line;
- oldcol = ctxt->input->col;
+ inputid = ctxt->input->id;
nbatts = 0;
nratts = 0;
nbdef = 0;
*/
SKIP_BLANKS;
GROW;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
while (((RAW != '>') &&
((RAW != '/') || (NXT(1) != '>')) &&
attname = xmlParseAttribute2(ctxt, prefix, localname,
&aprefix, &attvalue, &len, &alloc);
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr)) {
- if ((attvalue != NULL) && (alloc != 0))
- xmlFree(attvalue);
- attvalue = NULL;
- goto base_changed;
- }
- if ((attname != NULL) && (attvalue != NULL)) {
- if (len < 0) len = xmlStrlen(attvalue);
- if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
- const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
- xmlURIPtr uri;
-
- if (URL == NULL) {
- xmlErrMemory(ctxt, "dictionary allocation failure");
- if ((attvalue != NULL) && (alloc != 0))
- xmlFree(attvalue);
- return(NULL);
- }
- if (*URL != 0) {
- uri = xmlParseURI((const char *) URL);
- if (uri == NULL) {
- xmlNsErr(ctxt, XML_WAR_NS_URI,
- "xmlns: '%s' is not a valid URI\n",
- URL, NULL, NULL);
- } else {
- if (uri->scheme == NULL) {
- xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
- "xmlns: URI %s is not absolute\n",
- URL, NULL, NULL);
- }
- xmlFreeURI(uri);
- }
- if (URL == ctxt->str_xml_ns) {
- if (attname != ctxt->str_xml) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "xml namespace URI cannot be the default namespace\n",
- NULL, NULL, NULL);
- }
- goto skip_default_ns;
- }
- if ((len == 29) &&
- (xmlStrEqual(URL,
- BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "reuse of the xmlns namespace name is forbidden\n",
- NULL, NULL, NULL);
- goto skip_default_ns;
- }
- }
- /*
- * check that it's not a defined namespace
- */
- for (j = 1;j <= nbNs;j++)
- if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
- break;
- if (j <= nbNs)
- xmlErrAttributeDup(ctxt, NULL, attname);
- else
- if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
-skip_default_ns:
- if (alloc != 0) xmlFree(attvalue);
- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
- break;
- if (!IS_BLANK_CH(RAW)) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "attributes construct error\n");
- break;
- }
- SKIP_BLANKS;
- continue;
- }
- if (aprefix == ctxt->str_xmlns) {
- const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
- xmlURIPtr uri;
-
- if (attname == ctxt->str_xml) {
- if (URL != ctxt->str_xml_ns) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "xml namespace prefix mapped to wrong URI\n",
- NULL, NULL, NULL);
- }
- /*
- * Do not keep a namespace definition node
- */
- goto skip_ns;
- }
+ if ((attname == NULL) || (attvalue == NULL))
+ goto next_attr;
+ if (len < 0) len = xmlStrlen(attvalue);
+
+ if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
+ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+ xmlURIPtr uri;
+
+ if (URL == NULL) {
+ xmlErrMemory(ctxt, "dictionary allocation failure");
+ if ((attvalue != NULL) && (alloc != 0))
+ xmlFree(attvalue);
+ return(NULL);
+ }
+ if (*URL != 0) {
+ uri = xmlParseURI((const char *) URL);
+ if (uri == NULL) {
+ xmlNsErr(ctxt, XML_WAR_NS_URI,
+ "xmlns: '%s' is not a valid URI\n",
+ URL, NULL, NULL);
+ } else {
+ if (uri->scheme == NULL) {
+ xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+ "xmlns: URI %s is not absolute\n",
+ URL, NULL, NULL);
+ }
+ xmlFreeURI(uri);
+ }
if (URL == ctxt->str_xml_ns) {
- if (attname != ctxt->str_xml) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "xml namespace URI mapped to wrong prefix\n",
- NULL, NULL, NULL);
- }
- goto skip_ns;
- }
- if (attname == ctxt->str_xmlns) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "redefinition of the xmlns prefix is forbidden\n",
- NULL, NULL, NULL);
- goto skip_ns;
- }
- if ((len == 29) &&
- (xmlStrEqual(URL,
- BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "reuse of the xmlns namespace name is forbidden\n",
- NULL, NULL, NULL);
- goto skip_ns;
- }
- if ((URL == NULL) || (URL[0] == 0)) {
- xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
- "xmlns:%s: Empty XML namespace is not allowed\n",
- attname, NULL, NULL);
- goto skip_ns;
- } else {
- uri = xmlParseURI((const char *) URL);
- if (uri == NULL) {
- xmlNsErr(ctxt, XML_WAR_NS_URI,
- "xmlns:%s: '%s' is not a valid URI\n",
- attname, URL, NULL);
- } else {
- if ((ctxt->pedantic) && (uri->scheme == NULL)) {
- xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
- "xmlns:%s: URI %s is not absolute\n",
- attname, URL, NULL);
- }
- xmlFreeURI(uri);
- }
- }
-
- /*
- * check that it's not a defined namespace
- */
- for (j = 1;j <= nbNs;j++)
- if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
- break;
- if (j <= nbNs)
- xmlErrAttributeDup(ctxt, aprefix, attname);
- else
- if (nsPush(ctxt, attname, URL) > 0) nbNs++;
-skip_ns:
- if (alloc != 0) xmlFree(attvalue);
- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
- break;
- if (!IS_BLANK_CH(RAW)) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "attributes construct error\n");
- break;
- }
- SKIP_BLANKS;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
- continue;
- }
+ if (attname != ctxt->str_xml) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "xml namespace URI cannot be the default namespace\n",
+ NULL, NULL, NULL);
+ }
+ goto next_attr;
+ }
+ if ((len == 29) &&
+ (xmlStrEqual(URL,
+ BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "reuse of the xmlns namespace name is forbidden\n",
+ NULL, NULL, NULL);
+ goto next_attr;
+ }
+ }
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
+ break;
+ if (j <= nbNs)
+ xmlErrAttributeDup(ctxt, NULL, attname);
+ else
+ if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
+
+ } else if (aprefix == ctxt->str_xmlns) {
+ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+ xmlURIPtr uri;
+
+ if (attname == ctxt->str_xml) {
+ if (URL != ctxt->str_xml_ns) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "xml namespace prefix mapped to wrong URI\n",
+ NULL, NULL, NULL);
+ }
+ /*
+ * Do not keep a namespace definition node
+ */
+ goto next_attr;
+ }
+ if (URL == ctxt->str_xml_ns) {
+ if (attname != ctxt->str_xml) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "xml namespace URI mapped to wrong prefix\n",
+ NULL, NULL, NULL);
+ }
+ goto next_attr;
+ }
+ if (attname == ctxt->str_xmlns) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "redefinition of the xmlns prefix is forbidden\n",
+ NULL, NULL, NULL);
+ goto next_attr;
+ }
+ if ((len == 29) &&
+ (xmlStrEqual(URL,
+ BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "reuse of the xmlns namespace name is forbidden\n",
+ NULL, NULL, NULL);
+ goto next_attr;
+ }
+ if ((URL == NULL) || (URL[0] == 0)) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "xmlns:%s: Empty XML namespace is not allowed\n",
+ attname, NULL, NULL);
+ goto next_attr;
+ } else {
+ uri = xmlParseURI((const char *) URL);
+ if (uri == NULL) {
+ xmlNsErr(ctxt, XML_WAR_NS_URI,
+ "xmlns:%s: '%s' is not a valid URI\n",
+ attname, URL, NULL);
+ } else {
+ if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+ xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+ "xmlns:%s: URI %s is not absolute\n",
+ attname, URL, NULL);
+ }
+ xmlFreeURI(uri);
+ }
+ }
- /*
- * Add the pair to atts
- */
- if ((atts == NULL) || (nbatts + 5 > maxatts)) {
- if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
- if (attvalue[len] == 0)
- xmlFree(attvalue);
- goto failed;
- }
- maxatts = ctxt->maxatts;
- atts = ctxt->atts;
- }
- ctxt->attallocs[nratts++] = alloc;
- atts[nbatts++] = attname;
- atts[nbatts++] = aprefix;
- atts[nbatts++] = NULL; /* the URI will be fetched later */
- atts[nbatts++] = attvalue;
- attvalue += len;
- atts[nbatts++] = attvalue;
- /*
- * tag if some deallocation is needed
- */
- if (alloc != 0) attval = 1;
- } else {
- if ((attvalue != NULL) && (attvalue[len] == 0))
- xmlFree(attvalue);
- }
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
+ break;
+ if (j <= nbNs)
+ xmlErrAttributeDup(ctxt, aprefix, attname);
+ else
+ if (nsPush(ctxt, attname, URL) > 0) nbNs++;
+
+ } else {
+ /*
+ * Add the pair to atts
+ */
+ if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+ if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+ goto next_attr;
+ }
+ maxatts = ctxt->maxatts;
+ atts = ctxt->atts;
+ }
+ ctxt->attallocs[nratts++] = alloc;
+ atts[nbatts++] = attname;
+ atts[nbatts++] = aprefix;
+ /*
+ * The namespace URI field is used temporarily to point at the
+ * base of the current input buffer for non-alloced attributes.
+ * When the input buffer is reallocated, all the pointers become
+ * invalid, but they can be reconstructed later.
+ */
+ if (alloc)
+ atts[nbatts++] = NULL;
+ else
+ atts[nbatts++] = ctxt->input->base;
+ atts[nbatts++] = attvalue;
+ attvalue += len;
+ atts[nbatts++] = attvalue;
+ /*
+ * tag if some deallocation is needed
+ */
+ if (alloc != 0) attval = 1;
+ attvalue = NULL; /* moved into atts */
+ }
-failed:
+next_attr:
+ if ((attvalue != NULL) && (alloc != 0)) {
+ xmlFree(attvalue);
+ attvalue = NULL;
+ }
GROW
if (ctxt->instate == XML_PARSER_EOF)
break;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
break;
- if (!IS_BLANK_CH(RAW)) {
+ if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"attributes construct error\n");
break;
}
- SKIP_BLANKS;
if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
(attname == NULL) && (attvalue == NULL)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
break;
}
GROW;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
+ }
+
+ if (ctxt->input->id != inputid) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "Unexpected change of input\n");
+ localname = NULL;
+ goto done;
+ }
+
+ /* Reconstruct attribute value pointers. */
+ for (i = 0, j = 0; j < nratts; i += 5, j++) {
+ if (atts[i+2] != NULL) {
+ /*
+ * Arithmetic on dangling pointers is technically undefined
+ * behavior, but well...
+ */
+ ptrdiff_t offset = ctxt->input->base - atts[i+2];
+ atts[i+2] = NULL; /* Reset repurposed namespace URI */
+ atts[i+3] += offset; /* value */
+ atts[i+4] += offset; /* valuend */
+ }
}
/*
nsname, 0, NULL, nbatts / 5, nbdef, atts);
}
+done:
/*
* Free up attribute allocated strings if needed
*/
}
return(localname);
-
-base_changed:
- /*
- * the attribute strings are valid iif the base didn't changed
- */
- if (attval != 0) {
- for (i = 3,j = 0; j < nratts;i += 5,j++)
- if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
- xmlFree((xmlChar *) atts[i]);
- }
-
- /*
- * We can't switch from one entity to another in the middle
- * of a start tag
- */
- if (inputNr != ctxt->inputNr) {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Start tag doesn't start and stop in the same entity\n");
- return(NULL);
- }
-
- ctxt->input->cur = ctxt->input->base + cur;
- ctxt->input->line = oldline;
- ctxt->input->col = oldcol;
- if (ctxt->wellFormed == 1) {
- goto reparse;
- }
- return(NULL);
}
/**
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
const xmlChar *URI, int line, int nsNr, int tlen) {
const xmlChar *name;
+ size_t curLength;
GROW;
if ((RAW != '<') || (NXT(1) != '/')) {
}
SKIP(2);
- if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
- if (ctxt->input->cur[tlen] == '>') {
+ curLength = ctxt->input->end - ctxt->input->cur;
+ if ((tlen > 0) && (curLength >= (size_t)tlen) &&
+ (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
+ if ((curLength >= (size_t)(tlen + 1)) &&
+ (ctxt->input->cur[tlen] == '>')) {
ctxt->input->cur += tlen + 1;
ctxt->input->col += tlen + 1;
goto done;
}
GROW;
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
SHRINK;
if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
}
/**
* xmlCheckCdataPush:
- * @cur: pointer to the bock of characters
+ * @cur: pointer to the block of characters
* @len: length of the block in bytes
+ * @complete: 1 if complete CDATA block is passed in, 0 if partial block
*
* Check that the block of characters is okay as SCdata content [20]
*
* Returns the number of bytes to pass if okay, a negative index where an
- * UTF-8 error occured otherwise
+ * UTF-8 error occurred otherwise
*/
static int
-xmlCheckCdataPush(const xmlChar *utf, int len) {
+xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
int ix;
unsigned char c;
int codepoint;
else
return(-ix);
} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
- if (ix + 2 > len) return(-ix);
+ if (ix + 2 > len) return(complete ? -ix : ix);
if ((utf[ix+1] & 0xc0 ) != 0x80)
return(-ix);
codepoint = (utf[ix] & 0x1f) << 6;
return(-ix);
ix += 2;
} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
- if (ix + 3 > len) return(-ix);
+ if (ix + 3 > len) return(complete ? -ix : ix);
if (((utf[ix+1] & 0xc0) != 0x80) ||
((utf[ix+2] & 0xc0) != 0x80))
return(-ix);
return(-ix);
ix += 3;
} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
- if (ix + 4 > len) return(-ix);
+ if (ix + 4 > len) return(complete ? -ix : ix);
if (((utf[ix+1] & 0xc0) != 0x80) ||
((utf[ix+2] & 0xc0) != 0x80) ||
((utf[ix+3] & 0xc0) != 0x80))
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
return(0);
-
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
-
if (ctxt->input == NULL) break;
if (ctxt->input->buf == NULL)
avail = ctxt->input->length -
ctxt->checkIndex = 0;
xmlParseCharData(ctxt, 0);
}
- /*
- * Pop-up of finished entities.
- */
- while ((RAW == 0) && (ctxt->inputNr > 1))
- xmlPopInput(ctxt);
if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
"detected an error in element content\n");
}
if (ctxt->sax2) {
xmlParseEndTag2(ctxt,
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
- (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
+ (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
+ (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
+ (int) (ptrdiff_t)
+ ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
nameNsPop(ctxt);
}
#ifdef LIBXML_SAX1_ENABLED
int tmp;
tmp = xmlCheckCdataPush(ctxt->input->cur,
- XML_PARSER_BIG_BUFFER_SIZE);
+ XML_PARSER_BIG_BUFFER_SIZE, 0);
if (tmp < 0) {
tmp = -tmp;
ctxt->input->cur += tmp;
} else {
int tmp;
- tmp = xmlCheckCdataPush(ctxt->input->cur, base);
+ tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
if ((tmp < 0) || (tmp != base)) {
tmp = -tmp;
ctxt->input->cur += tmp;
/* TODO 2.6.0 */
xmlGenericError(xmlGenericErrorContext,
"xmlParseChunk: encoder error\n");
+ xmlHaltParser(ctxt);
return(XML_ERR_INVALID_ENCODING);
}
xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
return;
ctxt->instate = XML_PARSER_EOF;
ctxt->disableSAX = 1;
+ while (ctxt->inputNr > 1)
+ xmlFreeInputStream(inputPop(ctxt));
if (ctxt->input != NULL) {
/*
* in case there was a specific allocation deallocate before
ctxt->input->free((xmlChar *) ctxt->input->base);
ctxt->input->free = NULL;
}
+ if (ctxt->input->buf != NULL) {
+ xmlFreeParserInputBuffer(ctxt->input->buf);
+ ctxt->input->buf = NULL;
+ }
ctxt->input->cur = BAD_CAST"";
+ ctxt->input->length = 0;
ctxt->input->base = ctxt->input->cur;
+ ctxt->input->end = ctxt->input->cur;
}
}
/*
* And record the last error if any
*/
- if (ctxt->lastError.code != XML_ERR_OK)
+ if ((oldctxt != NULL) && (ctxt->lastError.code != XML_ERR_OK))
xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
if (sax != NULL)
ctxt->userData = ctxt;
if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
ctxt->dict = oldctxt->dict;
+ ctxt->input_id = oldctxt->input_id + 1;
ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
xmlDetectSAX2(ctxt);
ctxt->myDoc = doc;
/* parsing in context, i.e. as within existing content */
+ ctxt->input_id = 2;
ctxt->instate = XML_PARSER_CONTENT;
fake = xmlNewComment(NULL);
newDoc->oldNs = doc->oldNs;
}
ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->input_id = 2;
ctxt->depth = depth;
/*
if (pctx != NULL) {
ctxt->options = pctx->options;
ctxt->_private = pctx->_private;
+ /*
+ * this is a subparser of pctx, so the input_id should be
+ * incremented to distinguish from main entity
+ */
+ ctxt->input_id = pctx->input_id + 1;
}
uri = xmlBuildURI(URL, base);
* DICT_FREE:
* @str: a string
*
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
* current scope
*/
#define DICT_FREE(str) \
xmlInitNodeInfoSeq(&ctxt->node_seq);
if (ctxt->attsDefault != NULL) {
- xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+ xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
ctxt->attsDefault = NULL;
}
if (ctxt->attsSpecial != NULL) {
void *catalogs; /* document's own catalog */
int recovery; /* run in recovery mode */
int progressive; /* is this a progressive parsing */
- xmlDictPtr dict; /* dictionnary for the parser */
+ xmlDictPtr dict; /* dictionary for the parser */
const xmlChar * *atts; /* array for the attributes callbacks */
int maxatts; /* the size of the array */
int docdict; /* use strings from dict to build tree */
XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */
XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitition */
XML_PARSE_NONET = 1<<11,/* Forbid network access */
- XML_PARSE_NODICT = 1<<12,/* Do not reuse the context dictionnary */
+ XML_PARSE_NODICT = 1<<12,/* Do not reuse the context dictionary */
XML_PARSE_NSCLEAN = 1<<13,/* remove redundant namespaces declarations */
XML_PARSE_NOCDATA = 1<<14,/* merge CDATA as text nodes */
XML_PARSE_NOXINCNODE= 1<<15,/* do not generate XINCLUDE START/END nodes */
#define IN_LIBXML
#include "libxml.h"
-#if defined(WIN32) && !defined (__CYGWIN__)
+#if defined(_WIN32) && !defined (__CYGWIN__)
#define XML_DIR_SEP '\\'
#else
#define XML_DIR_SEP '/'
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
#include <libxml/globals.h>
#include <libxml/chvalid.h>
+#define CUR(ctxt) ctxt->input->cur
+#define END(ctxt) ctxt->input->end
+#define VALID_CTXT(ctxt) (CUR(ctxt) <= END(ctxt))
+
#include "buf.h"
#include "enc.h"
*
* Handle an internal error
*/
-static void
+static void LIBXML_ATTR_FORMAT(2,0)
xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
*
* n encoding error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, int val)
{
*/
int
xmlParserInputGrow(xmlParserInputPtr in, int len) {
- size_t ret;
+ int ret;
size_t indx;
const xmlChar *content;
(ctxt->input == NULL))
return;
+ if (!(VALID_CTXT(ctxt))) {
+ xmlErrInternal(ctxt, "Parser input data memory error\n", NULL);
+ ctxt->errNo = XML_ERR_INTERNAL_ERROR;
+ xmlStopParser(ctxt);
+ return;
+ }
+
+ if ((*ctxt->input->cur == 0) &&
+ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {
+ return;
+ }
+
if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
- if ((*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0) &&
- (ctxt->instate != XML_PARSER_COMMENT)) {
- /*
- * If we are at the end of the current entity and
- * the context allows it, we pop consumed entities
- * automatically.
- * the auto closing should be blocked in other cases
- */
- xmlPopInput(ctxt);
- } else {
- const unsigned char *cur;
- unsigned char c;
+ const unsigned char *cur;
+ unsigned char c;
- /*
- * 2.11 End-of-Line Handling
- * the literal two-character sequence "#xD#xA" or a standalone
- * literal #xD, an XML processor must pass to the application
- * the single character #xA.
- */
- if (*(ctxt->input->cur) == '\n') {
- ctxt->input->line++; ctxt->input->col = 1;
- } else
- ctxt->input->col++;
+ /*
+ * 2.11 End-of-Line Handling
+ * the literal two-character sequence "#xD#xA" or a standalone
+ * literal #xD, an XML processor must pass to the application
+ * the single character #xA.
+ */
+ if (*(ctxt->input->cur) == '\n') {
+ ctxt->input->line++; ctxt->input->col = 1;
+ } else
+ ctxt->input->col++;
- /*
- * We are supposed to handle UTF8, check it's valid
- * From rfc2044: encoding of the Unicode values on UTF-8:
- *
- * UCS-4 range (hex.) UTF-8 octet sequence (binary)
- * 0000 0000-0000 007F 0xxxxxxx
- * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
- * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
- *
- * Check for the 0x110000 limit too
- */
- cur = ctxt->input->cur;
+ /*
+ * We are supposed to handle UTF8, check it's valid
+ * From rfc2044: encoding of the Unicode values on UTF-8:
+ *
+ * UCS-4 range (hex.) UTF-8 octet sequence (binary)
+ * 0000 0000-0000 007F 0xxxxxxx
+ * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
+ * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
+ *
+ * Check for the 0x110000 limit too
+ */
+ cur = ctxt->input->cur;
- c = *cur;
- if (c & 0x80) {
- if (c == 0xC0)
- goto encoding_error;
- if (cur[1] == 0) {
+ c = *cur;
+ if (c & 0x80) {
+ if (c == 0xC0)
+ goto encoding_error;
+ if (cur[1] == 0) {
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ cur = ctxt->input->cur;
+ }
+ if ((cur[1] & 0xc0) != 0x80)
+ goto encoding_error;
+ if ((c & 0xe0) == 0xe0) {
+ unsigned int val;
+
+ if (cur[2] == 0) {
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
cur = ctxt->input->cur;
}
- if ((cur[1] & 0xc0) != 0x80)
+ if ((cur[2] & 0xc0) != 0x80)
goto encoding_error;
- if ((c & 0xe0) == 0xe0) {
- unsigned int val;
-
- if (cur[2] == 0) {
+ if ((c & 0xf0) == 0xf0) {
+ if (cur[3] == 0) {
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
cur = ctxt->input->cur;
}
- if ((cur[2] & 0xc0) != 0x80)
+ if (((c & 0xf8) != 0xf0) ||
+ ((cur[3] & 0xc0) != 0x80))
goto encoding_error;
- if ((c & 0xf0) == 0xf0) {
- if (cur[3] == 0) {
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
- cur = ctxt->input->cur;
- }
- if (((c & 0xf8) != 0xf0) ||
- ((cur[3] & 0xc0) != 0x80))
- goto encoding_error;
- /* 4-byte code */
- ctxt->input->cur += 4;
- val = (cur[0] & 0x7) << 18;
- val |= (cur[1] & 0x3f) << 12;
- val |= (cur[2] & 0x3f) << 6;
- val |= cur[3] & 0x3f;
- } else {
- /* 3-byte code */
- ctxt->input->cur += 3;
- val = (cur[0] & 0xf) << 12;
- val |= (cur[1] & 0x3f) << 6;
- val |= cur[2] & 0x3f;
- }
- if (((val > 0xd7ff) && (val < 0xe000)) ||
- ((val > 0xfffd) && (val < 0x10000)) ||
- (val >= 0x110000)) {
- xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
- "Char 0x%X out of allowed range\n",
- val);
- }
- } else
- /* 2-byte code */
- ctxt->input->cur += 2;
+ /* 4-byte code */
+ ctxt->input->cur += 4;
+ val = (cur[0] & 0x7) << 18;
+ val |= (cur[1] & 0x3f) << 12;
+ val |= (cur[2] & 0x3f) << 6;
+ val |= cur[3] & 0x3f;
+ } else {
+ /* 3-byte code */
+ ctxt->input->cur += 3;
+ val = (cur[0] & 0xf) << 12;
+ val |= (cur[1] & 0x3f) << 6;
+ val |= cur[2] & 0x3f;
+ }
+ if (((val > 0xd7ff) && (val < 0xe000)) ||
+ ((val > 0xfffd) && (val < 0x10000)) ||
+ (val >= 0x110000)) {
+ xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n",
+ val);
+ }
} else
- /* 1-byte code */
- ctxt->input->cur++;
+ /* 2-byte code */
+ ctxt->input->cur += 2;
+ } else
+ /* 1-byte code */
+ ctxt->input->cur++;
- ctxt->nbChars++;
- if (*ctxt->input->cur == 0)
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
- }
+ ctxt->nbChars++;
} else {
/*
* Assume it's a fixed length encoding (1) with
ctxt->input->col++;
ctxt->input->cur++;
ctxt->nbChars++;
- if (*ctxt->input->cur == 0)
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
}
- if ((*ctxt->input->cur == '%') && (!ctxt->html))
- xmlParserHandlePEReference(ctxt);
- if ((*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
- xmlPopInput(ctxt);
+ if (*ctxt->input->cur == 0)
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
return;
encoding_error:
/*
break;
}
}
- if (handler == NULL)
+ /*
+ * TODO: We could recover from errors in external entites if we
+ * didn't stop the parser. But most callers of this function don't
+ * check the return value.
+ */
+ if (handler == NULL) {
+ xmlStopParser(ctxt);
return(-1);
+ }
ctxt->charset = XML_CHAR_ENCODING_UTF8;
ret = xmlSwitchToEncodingInt(ctxt, handler, len);
if ((ret < 0) || (ctxt->errNo == XML_I18N_CONV_FAILED)) {
*/
nbchars = xmlCharEncFirstLineInput(input->buf, len);
}
+ xmlBufResetInput(input->buf->buffer, input);
if (nbchars < 0) {
xmlErrInternal(ctxt,
"switching encoding: encoder error\n",
return (-1);
}
input->buf->rawconsumed += use - xmlBufUse(input->buf->raw);
- xmlBufResetInput(input->buf->buffer, input);
}
return (0);
} else if (input->length == 0) {
* size to be able to convert the buffer.
*/
xmlErrInternal(ctxt, "switching encoding : no input\n", NULL);
+ /*
+ * Callers assume that the input buffer takes ownership of the
+ * encoding handler. xmlCharEncCloseFunc frees unregistered
+ * handlers and avoids a memory leak.
+ */
+ xmlCharEncCloseFunc(handler);
return (-1);
}
+ /*
+ * We should actually raise an error here, see issue #34.
+ */
+ xmlCharEncCloseFunc(handler);
return (0);
}
if (ctxt->pushTab != NULL) xmlFree(ctxt->pushTab);
if (ctxt->attallocs != NULL) xmlFree(ctxt->attallocs);
if (ctxt->attsDefault != NULL)
- xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+ xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
if (ctxt->attsSpecial != NULL)
xmlHashFree(ctxt->attsSpecial, NULL);
if (ctxt->freeElems != NULL) {
xmlParserErrors xmlerr,
const char *msg,
const xmlChar * str1,
- const xmlChar * str2);
+ const xmlChar * str2) LIBXML_ATTR_FORMAT(3,0);
#endif
/**
ERROR5(NULL, NULL, NULL,
"xmlCompileAttributeTest : no namespace bound to prefix %s\n",
prefix);
+ XML_PAT_FREE_STRING(ctxt, prefix);
ctxt->error = 1;
goto error;
}
#include <string.h>
#include <stdio.h>
+#include <stddef.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
*
* Handle a Relax NG Parsing error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
*
* Handle a Relax NG Validation error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
#endif
}
}
+ if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) {
+ found = 1;
+ }
}
tmp = tmp2;
}
xmlFree(name);
}
}
- cur = cur->next;
+ if (IS_RELAXNG(cur, "div") && cur->children != NULL) {
+ cur = cur->children;
+ } else {
+ if (cur->next != NULL) {
+ cur = cur->next;
+ } else {
+ while (cur->parent != node && cur->parent->next == NULL) {
+ cur = cur->parent;
+ }
+ cur = cur->parent != node ? cur->parent->next : NULL;
+ }
+ }
}
const xmlChar * arg2)
{
char msg[1000];
+ xmlChar *result;
if (arg1 == NULL)
arg1 = BAD_CAST "";
snprintf(msg, 1000, "Unknown error code %d\n", err);
}
msg[1000 - 1] = 0;
- return (xmlStrdup((xmlChar *) msg));
+ result = xmlCharStrdup(msg);
+ return (xmlEscapeFormatString(&result));
}
/**
* Free the structure associated to the type library
*/
static void
-xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
+xmlRelaxNGFreeTypeLibrary(void *payload,
const xmlChar * namespace ATTRIBUTE_UNUSED)
{
+ xmlRelaxNGTypeLibraryPtr lib = (xmlRelaxNGTypeLibraryPtr) payload;
if (lib == NULL)
return;
if (lib->namespace != NULL)
xmlSchemaCleanupTypes();
if (xmlRelaxNGTypeInitialized == 0)
return;
- xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
- xmlRelaxNGFreeTypeLibrary);
+ xmlHashFree(xmlRelaxNGRegisteredTypes, xmlRelaxNGFreeTypeLibrary);
xmlRelaxNGTypeInitialized = 0;
}
* xmlRelaxNGGetElements:
* @ctxt: a Relax-NG parser context
* @def: the definition definition
- * @eora: gather elements (0) or attributes (1)
+ * @eora: gather elements (0), attributes (1) or elements and text (2)
*
* Compute the list of top elements a definition can generate
*
while (cur != NULL) {
if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
(cur->type == XML_RELAXNG_TEXT))) ||
- ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) {
+ ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE)) ||
+ ((eora == 2) && ((cur->type == XML_RELAXNG_DATATYPE) ||
+ (cur->type == XML_RELAXNG_ELEMENT) ||
+ (cur->type == XML_RELAXNG_LIST) ||
+ (cur->type == XML_RELAXNG_TEXT) ||
+ (cur->type == XML_RELAXNG_VALUE)))) {
if (ret == NULL) {
max = 10;
ret = (xmlRelaxNGDefinePtr *)
* algorithm
*/
static void
-xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def,
- xmlRelaxNGParserCtxtPtr ctxt,
- xmlChar * name ATTRIBUTE_UNUSED)
+xmlRelaxNGComputeInterleaves(void *payload, void *data,
+ const xmlChar * name ATTRIBUTE_UNUSED)
{
+ xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
+ xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
xmlRelaxNGDefinePtr cur, *tmp;
xmlRelaxNGPartitionPtr partitions = NULL;
if (cur->type == XML_RELAXNG_TEXT)
is_mixed++;
groups[nbgroups]->rule = cur;
- groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
+ groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 2);
groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
nbgroups++;
cur = cur->next;
if ((*tmp)->type == XML_RELAXNG_TEXT) {
res = xmlHashAddEntry2(partitions->triage,
BAD_CAST "#text", NULL,
- (void *) (long) (i + 1));
+ (void *) (ptrdiff_t) (i + 1));
if (res != 0)
is_determinist = -1;
} else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
res = xmlHashAddEntry2(partitions->triage,
(*tmp)->name, NULL,
- (void *) (long) (i + 1));
+ (void *) (ptrdiff_t) (i + 1));
else
res = xmlHashAddEntry2(partitions->triage,
(*tmp)->name, (*tmp)->ns,
- (void *) (long) (i + 1));
+ (void *) (ptrdiff_t) (i + 1));
if (res != 0)
is_determinist = -1;
} else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
res = xmlHashAddEntry2(partitions->triage,
BAD_CAST "#any", NULL,
- (void *) (long) (i + 1));
+ (void *) (ptrdiff_t) (i + 1));
else
res = xmlHashAddEntry2(partitions->triage,
BAD_CAST "#any", (*tmp)->ns,
- (void *) (long) (i + 1));
+ (void *) (ptrdiff_t) (i + 1));
if ((*tmp)->nameClass != NULL)
is_determinist = 2;
if (res != 0)
* Import import one references into the current grammar
*/
static void
-xmlRelaxNGParseImportRef(void *payload, void *data, xmlChar *name) {
+xmlRelaxNGParseImportRef(void *payload, void *data, const xmlChar *name) {
xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
int tmp;
xmlNodePtr child;
xmlRelaxNGDefinePtr last = NULL;
- ret = xmlRelaxNGNewDefine(ctxt, node);
- if (ret == NULL)
- return (NULL);
- ret->parent = def;
- ret->type = XML_RELAXNG_CHOICE;
+ if (def->type == XML_RELAXNG_CHOICE) {
+ ret = def;
+ } else {
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->parent = def;
+ ret->type = XML_RELAXNG_CHOICE;
+ }
if (node->children == NULL) {
xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
if (tmp != NULL) {
if (last == NULL) {
- last = ret->nameClass = tmp;
+ last = tmp;
} else {
last->next = tmp;
last = tmp;
* element of a given grammar using the same name.
*/
static void
-xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref,
- xmlRelaxNGParserCtxtPtr ctxt,
- const xmlChar * name)
+xmlRelaxNGCheckReference(void *payload, void *data, const xmlChar * name)
{
+ xmlRelaxNGDefinePtr ref = (xmlRelaxNGDefinePtr) payload;
+ xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
xmlRelaxNGGrammarPtr grammar;
xmlRelaxNGDefinePtr def, cur;
* element of a given grammar using the same name.
*/
static void
-xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define,
- xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * name)
+xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
{
+ xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) payload;
+ xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
xmlChar *combine;
int choiceOrInterleave = -1;
int missing = 0;
*/
xmlRelaxNGCombineStart(ctxt, ret);
if (ret->defs != NULL) {
- xmlHashScan(ret->defs, (xmlHashScanner) xmlRelaxNGCheckCombine,
- ctxt);
+ xmlHashScan(ret->defs, xmlRelaxNGCheckCombine, ctxt);
}
/*
* link together defines and refs in this grammar
*/
if (ret->refs != NULL) {
- xmlHashScan(ret->refs, (xmlHashScanner) xmlRelaxNGCheckReference,
- ctxt);
+ xmlHashScan(ret->refs, xmlRelaxNGCheckReference, ctxt);
}
* try to preprocess interleaves
*/
if (ctxt->interleaves != NULL) {
- xmlHashScan(ctxt->interleaves,
- (xmlHashScanner) xmlRelaxNGComputeInterleaves, ctxt);
+ xmlHashScan(ctxt->interleaves, xmlRelaxNGComputeInterleaves, ctxt);
}
/*
if (ret != 0) {
break;
}
- /* no break on purpose */
+ /* Falls through. */
case XML_RELAXNG_ZEROORMORE:{
xmlChar *cur, *temp;
return (1);
} else if (((node->type == XML_TEXT_NODE) ||
(node->type == XML_CDATA_SECTION_NODE)) &&
- (cur->type == XML_RELAXNG_TEXT)) {
+ ((cur->type == XML_RELAXNG_DATATYPE) ||
+ (cur->type == XML_RELAXNG_LIST) ||
+ (cur->type == XML_RELAXNG_TEXT) ||
+ (cur->type == XML_RELAXNG_VALUE))) {
return (1);
}
cur = list[i++];
if (tmp == NULL) {
i = nbgroups;
} else {
- i = ((long) tmp) - 1;
+ i = ((ptrdiff_t) tmp) - 1;
if (partitions->flags & IS_NEEDCHECK) {
group = partitions->groups[i];
if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
}
if (ctxt->errNr > errNr)
xmlRelaxNGPopErrors(ctxt, errNr);
- /* no break on purpose */
+ /* Falls through. */
case XML_RELAXNG_ZEROORMORE:{
int progress;
xmlRelaxNGStatesPtr states = NULL, res = NULL;
* Description: internal interfaces for the XML Schemas handling
* and schema validity checking
* The Schemas development is a Work In Progress.
- * Some of those interfaces are not garanteed to be API or ABI stable !
+ * Some of those interfaces are not guaranteed to be API or ABI stable !
*
* Copy: See Copyright for the status of this software.
*
typedef enum {
XML_SCHEMAS_UNKNOWN = 0,
- XML_SCHEMAS_STRING,
- XML_SCHEMAS_NORMSTRING,
- XML_SCHEMAS_DECIMAL,
- XML_SCHEMAS_TIME,
- XML_SCHEMAS_GDAY,
- XML_SCHEMAS_GMONTH,
- XML_SCHEMAS_GMONTHDAY,
- XML_SCHEMAS_GYEAR,
- XML_SCHEMAS_GYEARMONTH,
- XML_SCHEMAS_DATE,
- XML_SCHEMAS_DATETIME,
- XML_SCHEMAS_DURATION,
- XML_SCHEMAS_FLOAT,
- XML_SCHEMAS_DOUBLE,
- XML_SCHEMAS_BOOLEAN,
- XML_SCHEMAS_TOKEN,
- XML_SCHEMAS_LANGUAGE,
- XML_SCHEMAS_NMTOKEN,
- XML_SCHEMAS_NMTOKENS,
- XML_SCHEMAS_NAME,
- XML_SCHEMAS_QNAME,
- XML_SCHEMAS_NCNAME,
- XML_SCHEMAS_ID,
- XML_SCHEMAS_IDREF,
- XML_SCHEMAS_IDREFS,
- XML_SCHEMAS_ENTITY,
- XML_SCHEMAS_ENTITIES,
- XML_SCHEMAS_NOTATION,
- XML_SCHEMAS_ANYURI,
- XML_SCHEMAS_INTEGER,
- XML_SCHEMAS_NPINTEGER,
- XML_SCHEMAS_NINTEGER,
- XML_SCHEMAS_NNINTEGER,
- XML_SCHEMAS_PINTEGER,
- XML_SCHEMAS_INT,
- XML_SCHEMAS_UINT,
- XML_SCHEMAS_LONG,
- XML_SCHEMAS_ULONG,
- XML_SCHEMAS_SHORT,
- XML_SCHEMAS_USHORT,
- XML_SCHEMAS_BYTE,
- XML_SCHEMAS_UBYTE,
- XML_SCHEMAS_HEXBINARY,
- XML_SCHEMAS_BASE64BINARY,
- XML_SCHEMAS_ANYTYPE,
- XML_SCHEMAS_ANYSIMPLETYPE
+ XML_SCHEMAS_STRING = 1,
+ XML_SCHEMAS_NORMSTRING = 2,
+ XML_SCHEMAS_DECIMAL = 3,
+ XML_SCHEMAS_TIME = 4,
+ XML_SCHEMAS_GDAY = 5,
+ XML_SCHEMAS_GMONTH = 6,
+ XML_SCHEMAS_GMONTHDAY = 7,
+ XML_SCHEMAS_GYEAR = 8,
+ XML_SCHEMAS_GYEARMONTH = 9,
+ XML_SCHEMAS_DATE = 10,
+ XML_SCHEMAS_DATETIME = 11,
+ XML_SCHEMAS_DURATION = 12,
+ XML_SCHEMAS_FLOAT = 13,
+ XML_SCHEMAS_DOUBLE = 14,
+ XML_SCHEMAS_BOOLEAN = 15,
+ XML_SCHEMAS_TOKEN = 16,
+ XML_SCHEMAS_LANGUAGE = 17,
+ XML_SCHEMAS_NMTOKEN = 18,
+ XML_SCHEMAS_NMTOKENS = 19,
+ XML_SCHEMAS_NAME = 20,
+ XML_SCHEMAS_QNAME = 21,
+ XML_SCHEMAS_NCNAME = 22,
+ XML_SCHEMAS_ID = 23,
+ XML_SCHEMAS_IDREF = 24,
+ XML_SCHEMAS_IDREFS = 25,
+ XML_SCHEMAS_ENTITY = 26,
+ XML_SCHEMAS_ENTITIES = 27,
+ XML_SCHEMAS_NOTATION = 28,
+ XML_SCHEMAS_ANYURI = 29,
+ XML_SCHEMAS_INTEGER = 30,
+ XML_SCHEMAS_NPINTEGER = 31,
+ XML_SCHEMAS_NINTEGER = 32,
+ XML_SCHEMAS_NNINTEGER = 33,
+ XML_SCHEMAS_PINTEGER = 34,
+ XML_SCHEMAS_INT = 35,
+ XML_SCHEMAS_UINT = 36,
+ XML_SCHEMAS_LONG = 37,
+ XML_SCHEMAS_ULONG = 38,
+ XML_SCHEMAS_SHORT = 39,
+ XML_SCHEMAS_USHORT = 40,
+ XML_SCHEMAS_BYTE = 41,
+ XML_SCHEMAS_UBYTE = 42,
+ XML_SCHEMAS_HEXBINARY = 43,
+ XML_SCHEMAS_BASE64BINARY = 44,
+ XML_SCHEMAS_ANYTYPE = 45,
+ XML_SCHEMAS_ANYSIMPLETYPE = 46
} xmlSchemaValType;
/*
int flags; /* specific to this schematron */
void *_private; /* unused by the library */
- xmlDictPtr dict; /* the dictionnary used internally */
+ xmlDictPtr dict; /* the dictionary used internally */
const xmlChar *title; /* the title if any */
const char *buffer;
int size;
- xmlDictPtr dict; /* dictionnary for interned string names */
+ xmlDictPtr dict; /* dictionary for interned string names */
int nberrors;
int err;
*
* Handle a parser error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#elif defined HAVE_WIN32_THREADS
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifndef HAVE_COMPILER_TLS
#include <process.h>
#ifdef HAVE_PTHREAD_H
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
+ defined(__GLIBC__) && defined(__linux__)
+
static int libxml_is_threaded = -1;
-#if defined(__GNUC__) && defined(__GLIBC__)
-#ifdef linux
-#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
-extern int pthread_once (pthread_once_t *__once_control,
- void (*__init_routine) (void))
- __attribute((weak));
-extern void *pthread_getspecific (pthread_key_t __key)
- __attribute((weak));
-extern int pthread_setspecific (pthread_key_t __key,
- __const void *__pointer)
- __attribute((weak));
-extern int pthread_key_create (pthread_key_t *__key,
- void (*__destr_function) (void *))
- __attribute((weak));
-extern int pthread_key_delete (pthread_key_t __key)
- __attribute((weak));
-extern int pthread_mutex_init ()
- __attribute((weak));
-extern int pthread_mutex_destroy ()
- __attribute((weak));
-extern int pthread_mutex_lock ()
- __attribute((weak));
-extern int pthread_mutex_unlock ()
- __attribute((weak));
-extern int pthread_cond_init ()
- __attribute((weak));
-extern int pthread_cond_destroy ()
- __attribute((weak));
-extern int pthread_cond_wait ()
- __attribute((weak));
-extern int pthread_equal ()
- __attribute((weak));
-extern pthread_t pthread_self ()
- __attribute((weak));
-extern int pthread_key_create ()
- __attribute((weak));
-extern int pthread_key_delete ()
- __attribute((weak));
-extern int pthread_cond_signal ()
- __attribute((weak));
-#endif
-#endif /* linux */
-#endif /* defined(__GNUC__) && defined(__GLIBC__) */
+
+#define XML_PTHREAD_WEAK
+
+#pragma weak pthread_once
+#pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
+#pragma weak pthread_key_create
+#pragma weak pthread_key_delete
+#pragma weak pthread_mutex_init
+#pragma weak pthread_mutex_destroy
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_unlock
+#pragma weak pthread_cond_init
+#pragma weak pthread_cond_destroy
+#pragma weak pthread_cond_wait
+#pragma weak pthread_equal
+#pragma weak pthread_self
+#pragma weak pthread_key_create
+#pragma weak pthread_key_delete
+#pragma weak pthread_cond_signal
+
+#else /* __GNUC__, __GLIBC__, __linux__ */
+
+static int libxml_is_threaded = 1;
+
+#endif /* __GNUC__, __GLIBC__, __linux__ */
+
#endif /* HAVE_PTHREAD_H */
/*
static DWORD mainthread;
static struct {
DWORD done;
- DWORD control;
+ LONG control;
} run_once = { 0, 0};
static volatile LPCRITICAL_SECTION global_init_lock = NULL;
/* Make sure the global init lock is initialized and then lock it. */
#ifdef HAVE_PTHREAD_H
/* The mutex is statically initialized, so we just lock it. */
- if (pthread_mutex_lock != NULL)
- pthread_mutex_lock(&global_init_lock);
+#ifdef XML_PTHREAD_WEAK
+ if (pthread_mutex_lock == NULL)
+ return;
+#endif /* XML_PTHREAD_WEAK */
+ pthread_mutex_lock(&global_init_lock);
#elif defined HAVE_WIN32_THREADS
LPCRITICAL_SECTION cs;
/* Swap it into the global_init_lock */
#ifdef InterlockedCompareExchangePointer
- InterlockedCompareExchangePointer(&global_init_lock, cs, NULL);
+ InterlockedCompareExchangePointer((void **) &global_init_lock,
+ cs, NULL);
#else /* Use older void* version */
InterlockedCompareExchange((void **) &global_init_lock,
(void *) cs, NULL);
__xmlGlobalInitMutexUnlock(void)
{
#ifdef HAVE_PTHREAD_H
- if (pthread_mutex_unlock != NULL)
- pthread_mutex_unlock(&global_init_lock);
+#ifdef XML_PTHREAD_WEAK
+ if (pthread_mutex_unlock == NULL)
+ return;
+#endif /* XML_PTHREAD_WEAK */
+ pthread_mutex_unlock(&global_init_lock);
#elif defined HAVE_WIN32_THREADS
if (global_init_lock != NULL) {
LeaveCriticalSection(global_init_lock);
xmlInitThreads(void)
{
#ifdef HAVE_PTHREAD_H
+#ifdef XML_PTHREAD_WEAK
if (libxml_is_threaded == -1) {
if ((pthread_once != NULL) &&
(pthread_getspecific != NULL) &&
libxml_is_threaded = 0;
}
}
+#endif /* XML_PTHREAD_WEAK */
#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
InitializeCriticalSection(&cleanup_helpers_cs);
#endif
xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
#endif
#ifdef HAVE_PTHREAD_H
- if ((libxml_is_threaded) && (pthread_key_delete != NULL))
+ if (libxml_is_threaded != 0)
pthread_key_delete(globalkey);
once_control = once_control_init;
#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
#ifdef HAVE_PTHREAD_H
#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
#if defined(LIBXML_STATIC_FOR_DLL)
-BOOL XMLCALL
-xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+int XMLCALL
+xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
+ ATTRIBUTE_UNUSED void *lpvReserved)
#else
+/* declare to avoid "no previous prototype for 'DllMain'" warning */
+/* Note that we do NOT want to include this function declaration in
+ a public header because it's meant to be called by Windows itself,
+ not a program that uses this library. This also has to be exported. */
+
+XMLPUBFUN BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved);
+
BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
+ ATTRIBUTE_UNUSED LPVOID lpvReserved)
#endif
{
switch (fdwReason) {
XMLPUBFUN xmlGlobalStatePtr XMLCALL
xmlGetGlobalState(void);
-#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && defined(LIBXML_STATIC_FOR_DLL)
-int XMLCALL xmlDllMain(void *hinstDLL, unsigned long fdwReason, void *lpvReserved);
+#ifdef HAVE_PTHREAD_H
+#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#if defined(LIBXML_STATIC_FOR_DLL)
+int XMLCALL
+xmlDllMain(void *hinstDLL, unsigned long fdwReason,
+ void *lpvReserved);
+#endif
#endif
#ifdef __cplusplus
/*
- * taken from https://github.com/swenson/sort
- * Kept as is for the moment to be able to apply upstream patches for that
- * code, currently used only to speed up XPath node sorting, see xpath.c
+ * Taken from https://github.com/swenson/sort
+ * Revision: 05fd77bfec049ce8b7c408c4d3dd2d51ee061a15
+ * Removed all code unrelated to Timsort and made minor adjustments for
+ * cross-platform compatibility.
*/
/*
- * All code in this header, unless otherwise specified, is hereby licensed under the MIT Public License:
-
-Copyright (c) 2010 Christopher Swenson
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2010-2017 Christopher Swenson.
+ * Copyright (c) 2012 Vojtech Fried.
+ * Copyright (c) 2012 Google Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
-#else
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif defined(WIN32)
-typedef __int64 int64_t;
+#elif defined(_WIN32)
typedef unsigned __int64 uint64_t;
#endif
+
+#ifndef SORT_NAME
+#error "Must declare SORT_NAME"
#endif
-#ifndef MK_UINT64
-#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
-#define MK_UINT64(x) ((uint64_t)(x))
-#else
-#define MK_UINT64(x) x##ULL
+#ifndef SORT_TYPE
+#error "Must declare SORT_TYPE"
#endif
+
+#ifndef SORT_CMP
+#define SORT_CMP(x, y) ((x) < (y) ? -1 : ((x) == (y) ? 0 : 1))
#endif
+#ifndef TIM_SORT_STACK_SIZE
+#define TIM_SORT_STACK_SIZE 128
+#endif
+
+#define SORT_SWAP(x,y) {SORT_TYPE __SORT_SWAP_t = (x); (x) = (y); (y) = __SORT_SWAP_t;}
+
+
+/* Common, type-agnosting functions and constants that we don't want to declare twice. */
+#ifndef SORT_COMMON_H
+#define SORT_COMMON_H
+
#ifndef MAX
#define MAX(x,y) (((x) > (y) ? (x) : (y)))
#endif
+
#ifndef MIN
#define MIN(x,y) (((x) < (y) ? (x) : (y)))
#endif
-int compute_minrun(uint64_t);
+static int compute_minrun(const uint64_t);
#ifndef CLZ
-#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))
+#ifdef __GNUC__
#define CLZ __builtin_clzll
#else
-int clzll(uint64_t);
+static int clzll(uint64_t);
/* adapted from Hacker's Delight */
-int clzll(uint64_t x) /* {{{ */
-{
+static int clzll(uint64_t x) {
int n;
- if (x == 0) return(64);
+ if (x == 0) {
+ return 64;
+ }
+
n = 0;
- if (x <= MK_UINT64(0x00000000FFFFFFFF)) {n = n + 32; x = x << 32;}
- if (x <= MK_UINT64(0x0000FFFFFFFFFFFF)) {n = n + 16; x = x << 16;}
- if (x <= MK_UINT64(0x00FFFFFFFFFFFFFF)) {n = n + 8; x = x << 8;}
- if (x <= MK_UINT64(0x0FFFFFFFFFFFFFFF)) {n = n + 4; x = x << 4;}
- if (x <= MK_UINT64(0x3FFFFFFFFFFFFFFF)) {n = n + 2; x = x << 2;}
- if (x <= MK_UINT64(0x7FFFFFFFFFFFFFFF)) {n = n + 1;}
+
+ if (x <= 0x00000000FFFFFFFFL) {
+ n = n + 32;
+ x = x << 32;
+ }
+
+ if (x <= 0x0000FFFFFFFFFFFFL) {
+ n = n + 16;
+ x = x << 16;
+ }
+
+ if (x <= 0x00FFFFFFFFFFFFFFL) {
+ n = n + 8;
+ x = x << 8;
+ }
+
+ if (x <= 0x0FFFFFFFFFFFFFFFL) {
+ n = n + 4;
+ x = x << 4;
+ }
+
+ if (x <= 0x3FFFFFFFFFFFFFFFL) {
+ n = n + 2;
+ x = x << 2;
+ }
+
+ if (x <= 0x7FFFFFFFFFFFFFFFL) {
+ n = n + 1;
+ }
+
return n;
}
-/* }}} */
#define CLZ clzll
#endif
#endif
-int compute_minrun(uint64_t size) /* {{{ */
-{
+static __inline int compute_minrun(const uint64_t size) {
const int top_bit = 64 - CLZ(size);
const int shift = MAX(top_bit, 6) - 6;
const int minrun = size >> shift;
- const uint64_t mask = (MK_UINT64(1) << shift) - 1;
- if (mask & size) return minrun + 1;
- return minrun;
-}
-/* }}} */
-
-#ifndef SORT_NAME
-#error "Must declare SORT_NAME"
-#endif
+ const uint64_t mask = (1ULL << shift) - 1;
-#ifndef SORT_TYPE
-#error "Must declare SORT_TYPE"
-#endif
-
-#ifndef SORT_CMP
-#define SORT_CMP(x, y) ((x) < (y) ? -1 : ((x) == (y) ? 0 : 1))
-#endif
+ if (mask & size) {
+ return minrun + 1;
+ }
+ return minrun;
+}
-#define SORT_SWAP(x,y) {SORT_TYPE __SORT_SWAP_t = (x); (x) = (y); (y) = __SORT_SWAP_t;}
+#endif /* SORT_COMMON_H */
#define SORT_CONCAT(x, y) x ## _ ## y
#define SORT_MAKE_STR1(x, y) SORT_CONCAT(x,y)
#define SORT_MAKE_STR(x) SORT_MAKE_STR1(SORT_NAME,x)
-#define BINARY_INSERTION_FIND SORT_MAKE_STR(binary_insertion_find)
-#define BINARY_INSERTION_SORT_START SORT_MAKE_STR(binary_insertion_sort_start)
-#define BINARY_INSERTION_SORT SORT_MAKE_STR(binary_insertion_sort)
-#define REVERSE_ELEMENTS SORT_MAKE_STR(reverse_elements)
-#define COUNT_RUN SORT_MAKE_STR(count_run)
-#define CHECK_INVARIANT SORT_MAKE_STR(check_invariant)
-#define TIM_SORT SORT_MAKE_STR(tim_sort)
-#define TIM_SORT_RESIZE SORT_MAKE_STR(tim_sort_resize)
-#define TIM_SORT_MERGE SORT_MAKE_STR(tim_sort_merge)
-#define TIM_SORT_COLLAPSE SORT_MAKE_STR(tim_sort_collapse)
+#define BINARY_INSERTION_FIND SORT_MAKE_STR(binary_insertion_find)
+#define BINARY_INSERTION_SORT_START SORT_MAKE_STR(binary_insertion_sort_start)
+#define BINARY_INSERTION_SORT SORT_MAKE_STR(binary_insertion_sort)
+#define REVERSE_ELEMENTS SORT_MAKE_STR(reverse_elements)
+#define COUNT_RUN SORT_MAKE_STR(count_run)
+#define CHECK_INVARIANT SORT_MAKE_STR(check_invariant)
+#define TIM_SORT SORT_MAKE_STR(tim_sort)
+#define TIM_SORT_RESIZE SORT_MAKE_STR(tim_sort_resize)
+#define TIM_SORT_MERGE SORT_MAKE_STR(tim_sort_merge)
+#define TIM_SORT_COLLAPSE SORT_MAKE_STR(tim_sort_collapse)
-#define TIM_SORT_RUN_T SORT_MAKE_STR(tim_sort_run_t)
-#define TEMP_STORAGE_T SORT_MAKE_STR(temp_storage_t)
+#ifndef MAX
+#define MAX(x,y) (((x) > (y) ? (x) : (y)))
+#endif
+#ifndef MIN
+#define MIN(x,y) (((x) < (y) ? (x) : (y)))
+#endif
typedef struct {
- int64_t start;
- int64_t length;
+ size_t start;
+ size_t length;
} TIM_SORT_RUN_T;
+
void BINARY_INSERTION_SORT(SORT_TYPE *dst, const size_t size);
void TIM_SORT(SORT_TYPE *dst, const size_t size);
+
/* Function used to do a binary search for binary insertion sort */
-static int64_t BINARY_INSERTION_FIND(SORT_TYPE *dst, const SORT_TYPE x, const size_t size)
-{
- int64_t l, c, r;
- SORT_TYPE lx;
+static __inline size_t BINARY_INSERTION_FIND(SORT_TYPE *dst, const SORT_TYPE x,
+ const size_t size) {
+ size_t l, c, r;
SORT_TYPE cx;
l = 0;
r = size - 1;
c = r >> 1;
- lx = dst[l];
- /* check for beginning conditions */
- if (SORT_CMP(x, lx) < 0)
+ /* check for out of bounds at the beginning. */
+ if (SORT_CMP(x, dst[0]) < 0) {
return 0;
- else if (SORT_CMP(x, lx) == 0)
- {
- int64_t i = 1;
- while (SORT_CMP(x, dst[i]) == 0) i++;
- return i;
+ } else if (SORT_CMP(x, dst[r]) > 0) {
+ return r;
}
cx = dst[c];
- while (1)
- {
+
+ while (1) {
const int val = SORT_CMP(x, cx);
- if (val < 0)
- {
- if (c - l <= 1) return c;
+
+ if (val < 0) {
+ if (c - l <= 1) {
+ return c;
+ }
+
r = c;
- }
- else if (val > 0)
- {
- if (r - c <= 1) return c + 1;
+ } else { /* allow = for stability. The binary search favors the right. */
+ if (r - c <= 1) {
+ return c + 1;
+ }
+
l = c;
- lx = cx;
- }
- else
- {
- do
- {
- cx = dst[++c];
- } while (SORT_CMP(x, cx) == 0);
- return c;
}
+
c = l + ((r - l) >> 1);
cx = dst[c];
}
}
/* Binary insertion sort, but knowing that the first "start" entries are sorted. Used in timsort. */
-static void BINARY_INSERTION_SORT_START(SORT_TYPE *dst, const size_t start, const size_t size)
-{
- int64_t i;
- for (i = start; i < (int64_t) size; i++)
- {
- int64_t j;
+static void BINARY_INSERTION_SORT_START(SORT_TYPE *dst, const size_t start, const size_t size) {
+ size_t i;
+
+ for (i = start; i < size; i++) {
+ size_t j;
SORT_TYPE x;
- int64_t location;
+ size_t location;
+
/* If this entry is already correct, just move along */
- if (SORT_CMP(dst[i - 1], dst[i]) <= 0) continue;
+ if (SORT_CMP(dst[i - 1], dst[i]) <= 0) {
+ continue;
+ }
/* Else we need to find the right place, shift everything over, and squeeze in */
x = dst[i];
location = BINARY_INSERTION_FIND(dst, x, i);
- for (j = i - 1; j >= location; j--)
- {
+
+ for (j = i - 1; j >= location; j--) {
dst[j + 1] = dst[j];
+
+ if (j == 0) { /* check edge case because j is unsigned */
+ break;
+ }
}
+
dst[location] = x;
}
}
/* Binary insertion sort */
-void BINARY_INSERTION_SORT(SORT_TYPE *dst, const size_t size)
-{
+void BINARY_INSERTION_SORT(SORT_TYPE *dst, const size_t size) {
+ /* don't bother sorting an array of size <= 1 */
+ if (size <= 1) {
+ return;
+ }
+
BINARY_INSERTION_SORT_START(dst, 1, size);
}
/* timsort implementation, based on timsort.txt */
-static void REVERSE_ELEMENTS(SORT_TYPE *dst, int64_t start, int64_t end)
-{
- while (1)
- {
- if (start >= end) return;
+static __inline void REVERSE_ELEMENTS(SORT_TYPE *dst, size_t start, size_t end) {
+ while (1) {
+ if (start >= end) {
+ return;
+ }
+
SORT_SWAP(dst[start], dst[end]);
start++;
end--;
}
}
-static int64_t COUNT_RUN(SORT_TYPE *dst, const int64_t start, const size_t size)
-{
- int64_t curr;
- if (size - start == 1) return 1;
- if (start >= (int64_t) size - 2)
- {
- if (SORT_CMP(dst[size - 2], dst[size - 1]) > 0)
+static size_t COUNT_RUN(SORT_TYPE *dst, const size_t start, const size_t size) {
+ size_t curr;
+
+ if (size - start == 1) {
+ return 1;
+ }
+
+ if (start >= size - 2) {
+ if (SORT_CMP(dst[size - 2], dst[size - 1]) > 0) {
SORT_SWAP(dst[size - 2], dst[size - 1]);
+ }
+
return 2;
}
curr = start + 2;
- if (SORT_CMP(dst[start], dst[start + 1]) <= 0)
- {
+ if (SORT_CMP(dst[start], dst[start + 1]) <= 0) {
/* increasing run */
- while (1)
- {
- if (curr == (int64_t) size - 1) break;
- if (SORT_CMP(dst[curr - 1], dst[curr]) > 0) break;
+ while (1) {
+ if (curr == size - 1) {
+ break;
+ }
+
+ if (SORT_CMP(dst[curr - 1], dst[curr]) > 0) {
+ break;
+ }
+
curr++;
}
+
return curr - start;
- }
- else
- {
+ } else {
/* decreasing run */
- while (1)
- {
- if (curr == (int64_t) size - 1) break;
- if (SORT_CMP(dst[curr - 1], dst[curr]) <= 0) break;
+ while (1) {
+ if (curr == size - 1) {
+ break;
+ }
+
+ if (SORT_CMP(dst[curr - 1], dst[curr]) <= 0) {
+ break;
+ }
+
curr++;
}
+
/* reverse in-place */
REVERSE_ELEMENTS(dst, start, curr - 1);
return curr - start;
}
}
-#define PUSH_NEXT() do {\
-len = COUNT_RUN(dst, curr, size);\
-run = minrun;\
-if (run < minrun) run = minrun;\
-if (run > (int64_t) size - curr) run = size - curr;\
-if (run > len)\
-{\
- BINARY_INSERTION_SORT_START(&dst[curr], len, run);\
- len = run;\
-}\
-{\
-run_stack[stack_curr].start = curr;\
-run_stack[stack_curr].length = len;\
-stack_curr++;\
-}\
-curr += len;\
-if (curr == (int64_t) size)\
-{\
- /* finish up */ \
- while (stack_curr > 1) \
- { \
- TIM_SORT_MERGE(dst, run_stack, stack_curr, store); \
- run_stack[stack_curr - 2].length += run_stack[stack_curr - 1].length; \
- stack_curr--; \
- } \
- if (store->storage != NULL)\
- {\
- free(store->storage);\
- store->storage = NULL;\
- }\
- return;\
-}\
-}\
-while (0)
-
-static int CHECK_INVARIANT(TIM_SORT_RUN_T *stack, const int stack_curr)
-{
- int64_t A, B, C;
- if (stack_curr < 2) return 1;
- if (stack_curr == 2)
- {
- const int64_t A1 = stack[stack_curr - 2].length;
- const int64_t B1 = stack[stack_curr - 1].length;
- if (A1 <= B1) return 0;
+static int CHECK_INVARIANT(TIM_SORT_RUN_T *stack, const int stack_curr) {
+ size_t A, B, C;
+
+ if (stack_curr < 2) {
return 1;
}
+
+ if (stack_curr == 2) {
+ const size_t A1 = stack[stack_curr - 2].length;
+ const size_t B1 = stack[stack_curr - 1].length;
+
+ if (A1 <= B1) {
+ return 0;
+ }
+
+ return 1;
+ }
+
A = stack[stack_curr - 3].length;
B = stack[stack_curr - 2].length;
C = stack[stack_curr - 1].length;
- if ((A <= B + C) || (B <= C)) return 0;
+
+ if ((A <= B + C) || (B <= C)) {
+ return 0;
+ }
+
return 1;
}
SORT_TYPE *storage;
} TEMP_STORAGE_T;
-
-static void TIM_SORT_RESIZE(TEMP_STORAGE_T *store, const size_t new_size)
-{
- if (store->alloc < new_size)
- {
+static void TIM_SORT_RESIZE(TEMP_STORAGE_T *store, const size_t new_size) {
+ if (store->alloc < new_size) {
SORT_TYPE *tempstore = (SORT_TYPE *)realloc(store->storage, new_size * sizeof(SORT_TYPE));
- if (tempstore == NULL)
- {
- fprintf(stderr, "Error allocating temporary storage for tim sort: need %lu bytes", (unsigned long) (sizeof(SORT_TYPE) * new_size));
+
+ if (tempstore == NULL) {
+ fprintf(stderr, "Error allocating temporary storage for tim sort: need %lu bytes",
+ (unsigned long)(sizeof(SORT_TYPE) * new_size));
exit(1);
}
+
store->storage = tempstore;
store->alloc = new_size;
}
}
-static void TIM_SORT_MERGE(SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const int stack_curr, TEMP_STORAGE_T *store)
-{
- const int64_t A = stack[stack_curr - 2].length;
- const int64_t B = stack[stack_curr - 1].length;
- const int64_t curr = stack[stack_curr - 2].start;
+static void TIM_SORT_MERGE(SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const int stack_curr,
+ TEMP_STORAGE_T *store) {
+ const size_t A = stack[stack_curr - 2].length;
+ const size_t B = stack[stack_curr - 1].length;
+ const size_t curr = stack[stack_curr - 2].start;
SORT_TYPE *storage;
- int64_t i, j, k;
-
+ size_t i, j, k;
TIM_SORT_RESIZE(store, MIN(A, B));
storage = store->storage;
/* left merge */
- if (A < B)
- {
+ if (A < B) {
memcpy(storage, &dst[curr], A * sizeof(SORT_TYPE));
i = 0;
j = curr + A;
- for (k = curr; k < curr + A + B; k++)
- {
- if ((i < A) && (j < curr + A + B))
- {
- if (SORT_CMP(storage[i], dst[j]) <= 0)
+ for (k = curr; k < curr + A + B; k++) {
+ if ((i < A) && (j < curr + A + B)) {
+ if (SORT_CMP(storage[i], dst[j]) <= 0) {
dst[k] = storage[i++];
- else
+ } else {
dst[k] = dst[j++];
- }
- else if (i < A)
- {
+ }
+ } else if (i < A) {
dst[k] = storage[i++];
+ } else {
+ break;
}
- else
- dst[k] = dst[j++];
}
- }
- /* right merge */
- else
- {
+ } else {
+ /* right merge */
memcpy(storage, &dst[curr + A], B * sizeof(SORT_TYPE));
- i = B - 1;
- j = curr + A - 1;
-
- for (k = curr + A + B - 1; k >= curr; k--)
- {
- if ((i >= 0) && (j >= curr))
- {
- if (SORT_CMP(dst[j], storage[i]) > 0)
- dst[k] = dst[j--];
- else
- dst[k] = storage[i--];
+ i = B;
+ j = curr + A;
+ k = curr + A + B;
+
+ while (k-- > curr) {
+ if ((i > 0) && (j > curr)) {
+ if (SORT_CMP(dst[j - 1], storage[i - 1]) > 0) {
+ dst[k] = dst[--j];
+ } else {
+ dst[k] = storage[--i];
+ }
+ } else if (i > 0) {
+ dst[k] = storage[--i];
+ } else {
+ break;
}
- else if (i >= 0)
- dst[k] = storage[i--];
- else
- dst[k] = dst[j--];
}
}
}
-static int TIM_SORT_COLLAPSE(SORT_TYPE *dst, TIM_SORT_RUN_T *stack, int stack_curr, TEMP_STORAGE_T *store, const size_t size)
-{
+static int TIM_SORT_COLLAPSE(SORT_TYPE *dst, TIM_SORT_RUN_T *stack, int stack_curr,
+ TEMP_STORAGE_T *store, const size_t size) {
while (1) {
- int64_t A, B, C, D;
- int ABC, BCD, BD, CD;
+ size_t A, B, C, D;
+ int ABC, BCD, CD;
/* if the stack only has one thing on it, we are done with the collapse */
if (stack_curr <= 1) {
BCD = (B <= C + D) || ABC;
CD = (C <= D);
- BD = (B < D);
/* Both invariants are good */
if (!BCD && !CD) {
return stack_curr;
}
-void TIM_SORT(SORT_TYPE *dst, const size_t size)
-{
- int minrun;
+static __inline int PUSH_NEXT(SORT_TYPE *dst,
+ const size_t size,
+ TEMP_STORAGE_T *store,
+ const size_t minrun,
+ TIM_SORT_RUN_T *run_stack,
+ size_t *stack_curr,
+ size_t *curr) {
+ size_t len = COUNT_RUN(dst, *curr, size);
+ size_t run = minrun;
+
+ if (run > size - *curr) {
+ run = size - *curr;
+ }
+
+ if (run > len) {
+ BINARY_INSERTION_SORT_START(&dst[*curr], len, run);
+ len = run;
+ }
+
+ run_stack[*stack_curr].start = *curr;
+ run_stack[*stack_curr].length = len;
+ (*stack_curr)++;
+ *curr += len;
+
+ if (*curr == size) {
+ /* finish up */
+ while (*stack_curr > 1) {
+ TIM_SORT_MERGE(dst, run_stack, *stack_curr, store);
+ run_stack[*stack_curr - 2].length += run_stack[*stack_curr - 1].length;
+ (*stack_curr)--;
+ }
+
+ if (store->storage != NULL) {
+ free(store->storage);
+ store->storage = NULL;
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+void TIM_SORT(SORT_TYPE *dst, const size_t size) {
+ size_t minrun;
TEMP_STORAGE_T _store, *store;
- TIM_SORT_RUN_T run_stack[128];
- int stack_curr = 0;
- int64_t len, run;
- int64_t curr = 0;
+ TIM_SORT_RUN_T run_stack[TIM_SORT_STACK_SIZE];
+ size_t stack_curr = 0;
+ size_t curr = 0;
- if (size < 64)
- {
+ /* don't bother sorting an array of size 1 */
+ if (size <= 1) {
+ return;
+ }
+
+ if (size < 64) {
BINARY_INSERTION_SORT(dst, size);
return;
}
/* compute the minimum run length */
minrun = compute_minrun(size);
-
/* temporary storage for merges */
store = &_store;
store->alloc = 0;
store->storage = NULL;
- PUSH_NEXT();
- PUSH_NEXT();
- PUSH_NEXT();
+ if (!PUSH_NEXT(dst, size, store, minrun, run_stack, &stack_curr, &curr)) {
+ return;
+ }
+
+ if (!PUSH_NEXT(dst, size, store, minrun, run_stack, &stack_curr, &curr)) {
+ return;
+ }
- while (1)
- {
- if (!CHECK_INVARIANT(run_stack, stack_curr))
- {
+ if (!PUSH_NEXT(dst, size, store, minrun, run_stack, &stack_curr, &curr)) {
+ return;
+ }
+
+ while (1) {
+ if (!CHECK_INVARIANT(run_stack, stack_curr)) {
stack_curr = TIM_SORT_COLLAPSE(dst, run_stack, stack_curr, store, size);
continue;
}
- PUSH_NEXT();
+
+ if (!PUSH_NEXT(dst, size, store, minrun, run_stack, &stack_curr, &curr)) {
+ return;
+ }
}
}
*
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
#include <string.h> /* for memset() only ! */
+#include <stddef.h>
#include <limits.h>
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
*
* [NS 7] LocalPart ::= NCName
*
- * Returns NULL if not a QName, otherwise the local part, and prefix
- * is updated to get the Prefix if any.
+ * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
+ * local part, and prefix is updated to get the Prefix. Both the return value
+ * and the prefix must be freed by the caller.
*/
-
xmlChar *
xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
int len = 0;
* DICT_FREE:
* @str: a string
*
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
* current scope
*/
#define DICT_FREE(str) \
* DICT_COPY:
* @str: a string
*
- * Copy a string using a "dict" dictionnary in the current scope,
+ * Copy a string using a "dict" dictionary in the current scope,
* if availabe.
*/
#define DICT_COPY(str, cpy) \
* DICT_CONST_COPY:
* @str: a string
*
- * Copy a string using a "dict" dictionnary in the current scope,
+ * Copy a string using a "dict" dictionary in the current scope,
* if availabe.
*/
#define DICT_CONST_COPY(str, cpy) \
else if ((ent != NULL) && (ent->children == NULL)) {
xmlNodePtr temp;
+ /* Set to non-NULL value to avoid recursion. */
+ ent->children = (xmlNodePtr) -1;
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
else if ((ent != NULL) && (ent->children == NULL)) {
xmlNodePtr temp;
+ /* Set to non-NULL value to avoid recursion. */
+ ent->children = (xmlNodePtr) -1;
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
temp = ent->children;
while (temp) {
temp->parent = (xmlNodePtr)ent;
+ ent->last = temp;
temp = temp->next;
}
}
cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
if (cur == NULL) {
xmlTreeErrMemory("building node");
- /* we can't check here that name comes from the doc dictionnary */
+ /* we can't check here that name comes from the doc dictionary */
return(NULL);
}
memset(cur, 0, sizeof(xmlNode));
UPDATE_LAST_CHILD_AND_PARENT(cur)
}
} else {
- /* if name don't come from the doc dictionnary free it here */
+ /* if name don't come from the doc dictionary free it here */
if ((name != NULL) && (doc != NULL) &&
(!(xmlDictOwns(doc->dict, name))))
xmlFree(name);
* When a node is a text node or a comment, it uses a global static
* variable for the name of the node.
* Otherwise the node name might come from the document's
- * dictionnary
+ * dictionary
*/
if ((cur->name != NULL) &&
(cur->type != XML_TEXT_NODE) &&
/*
* When a node is a text node or a comment, it uses a global static
* variable for the name of the node.
- * Otherwise the node name might come from the document's dictionnary
+ * Otherwise the node name might come from the document's dictionary
*/
if ((cur->name != NULL) &&
(cur->type != XML_TEXT_NODE) &&
(node->type == XML_PI_NODE)) {
if (node->line == 65535) {
if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
- result = (long) node->psvi;
+ result = (long) (ptrdiff_t) node->psvi;
else if ((node->type == XML_ELEMENT_NODE) &&
(node->children != NULL))
result = xmlGetLineNoInternal(node->children, depth + 1);
if (occur == 0) {
tmp = cur->next;
while (tmp != NULL && occur == 0) {
- if (tmp->type == XML_COMMENT_NODE)
- occur++;
+ if (tmp->type == XML_COMMENT_NODE)
+ occur++;
tmp = tmp->next;
}
if (occur != 0)
ns = ns->next;
} while (ns != NULL);
}
- /* No break on purpose. */
+ /* Falls through. */
case XML_ATTRIBUTE_NODE:
if (node->ns != NULL) {
/*
}
if (! adoptns)
goto ns_end;
- /* No break on purpose. */
+ /* Falls through. */
case XML_ATTRIBUTE_NODE:
/* No ns, no fun. */
if (cur->ns == NULL)
goto internal_error;
}
}
- /* No break on purpose. */
+ /* Falls through. */
case XML_ATTRIBUTE_NODE:
/* No namespace, no fun. */
if (cur->ns == NULL)
void *ids; /* Hash table for ID attributes if any */
void *refs; /* Hash table for IDREFs attributes if any */
const xmlChar *URL; /* The URI for that document */
- int charset; /* encoding of the in-memory content
+ int charset; /* Internal flag for charset handling,
actually an xmlCharEncoding */
struct _xmlDict *dict; /* dict used to allocate names or NULL */
void *psvi; /* for type/PSVI informations */
* @uri: pointer to an URI structure
* @str: the string to analyze
*
- * Parse a port part and fills in the appropriate fields
+ * Parse a port part and fills in the appropriate fields
* of the @uri structure
*
* port = *DIGIT
xmlParse3986Port(xmlURIPtr uri, const char **str)
{
const char *cur = *str;
+ unsigned port = 0; /* unsigned for defined overflow behavior */
if (ISA_DIGIT(cur)) {
- if (uri != NULL)
- uri->port = 0;
while (ISA_DIGIT(cur)) {
- if (uri != NULL)
- uri->port = uri->port * 10 + (*cur - '0');
+ port = port * 10 + (*cur - '0');
+
cur++;
}
+ if (uri != NULL)
+ uri->port = port & INT_MAX; /* port value modulo INT_MAX+1 */
*str = cur;
return(0);
}
res->scheme = xmlMemStrdup(bas->scheme);
if (bas->authority != NULL)
res->authority = xmlMemStrdup(bas->authority);
- else if (bas->server != NULL) {
- res->server = xmlMemStrdup(bas->server);
+ else if ((bas->server != NULL) || (bas->port == -1)) {
+ if (bas->server != NULL)
+ res->server = xmlMemStrdup(bas->server);
if (bas->user != NULL)
res->user = xmlMemStrdup(bas->user);
res->port = bas->port;
}
if (bas->authority != NULL)
res->authority = xmlMemStrdup(bas->authority);
- else if (bas->server != NULL) {
- res->server = xmlMemStrdup(bas->server);
+ else if ((bas->server != NULL) || (bas->port == -1)) {
+ if (bas->server != NULL)
+ res->server = xmlMemStrdup(bas->server);
if (bas->user != NULL)
res->user = xmlMemStrdup(bas->user);
res->port = bas->port;
xmlChar *val = NULL;
int ret;
int ix;
- int pos = 0;
int nbslash = 0;
int len;
xmlURIPtr ref = NULL;
* First we take care of the special case where either of the
* two path components may be missing (bug 316224)
*/
- if (bas->path == NULL) {
- if (ref->path != NULL) {
- uptr = (xmlChar *) ref->path;
- if (*uptr == '/')
- uptr++;
- /* exception characters from xmlSaveUri */
- val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
- }
- goto done;
- }
bptr = (xmlChar *)bas->path;
- if (ref->path == NULL) {
- for (ix = 0; bptr[ix] != 0; ix++) {
- if (bptr[ix] == '/')
- nbslash++;
- }
- uptr = NULL;
- len = 1; /* this is for a string terminator only */
- } else {
- /*
- * Next we compare the two strings and find where they first differ
- */
- if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
- pos += 2;
+ {
+ xmlChar *rptr = (xmlChar *) ref->path;
+ int pos = 0;
+
+ /*
+ * Next we compare the two strings and find where they first differ
+ */
+ if ((*rptr == '.') && (rptr[1] == '/'))
+ rptr += 2;
if ((*bptr == '.') && (bptr[1] == '/'))
bptr += 2;
- else if ((*bptr == '/') && (ref->path[pos] != '/'))
+ else if ((*bptr == '/') && (*rptr != '/'))
bptr++;
- while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
+ while ((bptr[pos] == rptr[pos]) && (bptr[pos] != 0))
pos++;
- if (bptr[pos] == ref->path[pos]) {
+ if (bptr[pos] == rptr[pos]) {
val = xmlStrdup(BAD_CAST "");
goto done; /* (I can't imagine why anyone would do this) */
}
* beginning of the "unique" suffix of URI
*/
ix = pos;
- if ((ref->path[ix] == '/') && (ix > 0))
- ix--;
- else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
- ix -= 2;
for (; ix > 0; ix--) {
- if (ref->path[ix] == '/')
+ if (rptr[ix - 1] == '/')
break;
}
- if (ix == 0) {
- uptr = (xmlChar *)ref->path;
- } else {
- ix++;
- uptr = (xmlChar *)&ref->path[ix];
- }
+ uptr = (xmlChar *)&rptr[ix];
/*
* In base, count the number of '/' from the differing point
*/
- if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */
- for (; bptr[ix] != 0; ix++) {
- if (bptr[ix] == '/')
- nbslash++;
- }
+ for (; bptr[ix] != 0; ix++) {
+ if (bptr[ix] == '/')
+ nbslash++;
+ }
+
+ /*
+ * e.g: URI="foo/" base="foo/bar" -> "./"
+ */
+ if (nbslash == 0 && !uptr[0]) {
+ val = xmlStrdup(BAD_CAST "./");
+ goto done;
}
+
len = xmlStrlen (uptr) + 1;
}
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
int len = 0;
- int i = 0;
- xmlChar *p = NULL;
+ char *p = NULL;
#endif
xmlURIPtr uri;
xmlChar *ret;
xmlFreeURI(uri);
return escURI;
}
+ xmlFree(escURI);
}
}
len = xmlStrlen(path);
if ((len > 2) && IS_WINDOWS_PATH(path)) {
/* make the scheme 'file' */
- uri->scheme = xmlStrdup(BAD_CAST "file");
+ uri->scheme = (char *) xmlStrdup(BAD_CAST "file");
/* allocate space for leading '/' + path + string terminator */
uri->path = xmlMallocAtomic(len + 2);
if (uri->path == NULL) {
/* Put in leading '/' plus path */
uri->path[0] = '/';
p = uri->path + 1;
- strncpy(p, path, len + 1);
+ strncpy(p, (char *) path, len + 1);
} else {
- uri->path = xmlStrdup(path);
+ uri->path = (char *) xmlStrdup(path);
if (uri->path == NULL) {
xmlFreeURI(uri);
return(NULL);
*
* Handle a validation error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const char *extra)
{
*
* Handle a validation error, provide contextual informations
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNode(xmlValidCtxtPtr ctxt,
xmlNodePtr node, xmlParserErrors error,
const char *msg, const xmlChar * str1,
__xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
XML_ERR_ERROR, NULL, 0,
(const char *) str1,
- (const char *) str1,
+ (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3);
}
#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
*
* Handle a validation error, provide contextual informations
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
xmlNodePtr node, xmlParserErrors error,
const char *msg, const xmlChar * str1,
*
* Handle a validation error, provide contextual information
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidWarning(xmlValidCtxtPtr ctxt,
xmlNodePtr node, xmlParserErrors error,
const char *msg, const xmlChar * str1,
__xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
XML_ERR_WARNING, NULL, 0,
(const char *) str1,
- (const char *) str1,
+ (const char *) str2,
(const char *) str3, 0, 0, msg, str1, str2, str3);
}
xmlBufferWriteCHAR(buf, content->name);
break;
case XML_ELEMENT_CONTENT_SEQ:
- if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
+ if ((content->c1 != NULL) &&
+ ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
+ (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
xmlDumpElementContent(buf, content->c1, 1);
else
xmlDumpElementContent(buf, content->c1, 0);
xmlBufferWriteChar(buf, " , ");
- if ((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
- ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) &&
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)))
+ if ((content->c2 != NULL) &&
+ ((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
+ ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) &&
+ (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
xmlDumpElementContent(buf, content->c2, 1);
else
xmlDumpElementContent(buf, content->c2, 0);
break;
case XML_ELEMENT_CONTENT_OR:
- if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
+ if ((content->c1 != NULL) &&
+ ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
+ (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
xmlDumpElementContent(buf, content->c1, 1);
else
xmlDumpElementContent(buf, content->c1, 0);
xmlBufferWriteChar(buf, " | ");
- if ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
- ((content->c2->type == XML_ELEMENT_CONTENT_OR) &&
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)))
+ if ((content->c2 != NULL) &&
+ ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
+ ((content->c2->type == XML_ELEMENT_CONTENT_OR) &&
+ (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
xmlDumpElementContent(buf, content->c2, 1);
else
xmlDumpElementContent(buf, content->c2, 0);
case XML_ELEMENT_CONTENT_PCDATA:
strcat(buf, "#PCDATA");
break;
- case XML_ELEMENT_CONTENT_ELEMENT:
+ case XML_ELEMENT_CONTENT_ELEMENT: {
+ int qnameLen = xmlStrlen(content->name);
+
+ if (content->prefix != NULL)
+ qnameLen += xmlStrlen(content->prefix) + 1;
+ if (size - len < qnameLen + 10) {
+ strcat(buf, " ...");
+ return;
+ }
if (content->prefix != NULL) {
- if (size - len < xmlStrlen(content->prefix) + 10) {
- strcat(buf, " ...");
- return;
- }
strcat(buf, (char *) content->prefix);
strcat(buf, ":");
}
- if (size - len < xmlStrlen(content->name) + 10) {
- strcat(buf, " ...");
- return;
- }
if (content->name != NULL)
strcat(buf, (char *) content->name);
break;
+ }
case XML_ELEMENT_CONTENT_SEQ:
if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
(content->c1->type == XML_ELEMENT_CONTENT_SEQ))
xmlSnprintfElementContent(buf, size, content->c2, 0);
break;
}
+ if (size - strlen(buf) <= 2) return;
if (englob)
strcat(buf, ")");
switch (content->ocur) {
return(ret);
}
+static void
+xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFreeElement((xmlElementPtr) elem);
+}
+
/**
* xmlFreeElementTable:
* @table: An element table
*/
void
xmlFreeElementTable(xmlElementTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeElement);
+ xmlHashFree(table, xmlFreeElementTableEntry);
}
#ifdef LIBXML_TREE_ENABLED
*
* Returns the new xmlElementPtr or NULL in case of error.
*/
-static xmlElementPtr
-xmlCopyElement(xmlElementPtr elem) {
+static void *
+xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlElementPtr elem = (xmlElementPtr) payload;
xmlElementPtr cur;
cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
*/
xmlElementTablePtr
xmlCopyElementTable(xmlElementTablePtr table) {
- return((xmlElementTablePtr) xmlHashCopy(table,
- (xmlHashCopier) xmlCopyElement));
+ return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement));
}
#endif /* LIBXML_TREE_ENABLED */
* the arguments.
*/
static void
-xmlDumpElementDeclScan(xmlElementPtr elem, xmlBufferPtr buf) {
- xmlDumpElementDecl(buf, elem);
+xmlDumpElementDeclScan(void *elem, void *buf,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
}
/**
xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
if ((buf == NULL) || (table == NULL))
return;
- xmlHashScan(table, (xmlHashScanner) xmlDumpElementDeclScan, buf);
+ xmlHashScan(table, xmlDumpElementDeclScan, buf);
}
#endif /* LIBXML_OUTPUT_ENABLED */
return(ret);
}
+static void
+xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFreeAttribute((xmlAttributePtr) attr);
+}
+
/**
* xmlFreeAttributeTable:
* @table: An attribute table
*/
void
xmlFreeAttributeTable(xmlAttributeTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeAttribute);
+ xmlHashFree(table, xmlFreeAttributeTableEntry);
}
#ifdef LIBXML_TREE_ENABLED
*
* Returns the new xmlAttributePtr or NULL in case of error.
*/
-static xmlAttributePtr
-xmlCopyAttribute(xmlAttributePtr attr) {
+static void *
+xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlAttributePtr attr = (xmlAttributePtr) payload;
xmlAttributePtr cur;
cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
*/
xmlAttributeTablePtr
xmlCopyAttributeTable(xmlAttributeTablePtr table) {
- return((xmlAttributeTablePtr) xmlHashCopy(table,
- (xmlHashCopier) xmlCopyAttribute));
+ return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute));
}
#endif /* LIBXML_TREE_ENABLED */
* This is used with the hash scan function - just reverses arguments
*/
static void
-xmlDumpAttributeDeclScan(xmlAttributePtr attr, xmlBufferPtr buf) {
- xmlDumpAttributeDecl(buf, attr);
+xmlDumpAttributeDeclScan(void *attr, void *buf,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
}
/**
xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
if ((buf == NULL) || (table == NULL))
return;
- xmlHashScan(table, (xmlHashScanner) xmlDumpAttributeDeclScan, buf);
+ xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
}
#endif /* LIBXML_OUTPUT_ENABLED */
return(ret);
}
+static void
+xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFreeNotation((xmlNotationPtr) nota);
+}
+
/**
* xmlFreeNotationTable:
* @table: An notation table
*/
void
xmlFreeNotationTable(xmlNotationTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeNotation);
+ xmlHashFree(table, xmlFreeNotationTableEntry);
}
#ifdef LIBXML_TREE_ENABLED
*
* Returns the new xmlNotationPtr or NULL in case of error.
*/
-static xmlNotationPtr
-xmlCopyNotation(xmlNotationPtr nota) {
+static void *
+xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlNotationPtr nota = (xmlNotationPtr) payload;
xmlNotationPtr cur;
cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
*/
xmlNotationTablePtr
xmlCopyNotationTable(xmlNotationTablePtr table) {
- return((xmlNotationTablePtr) xmlHashCopy(table,
- (xmlHashCopier) xmlCopyNotation));
+ return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation));
}
#endif /* LIBXML_TREE_ENABLED */
* This is called with the hash scan function, and just reverses args
*/
static void
-xmlDumpNotationDeclScan(xmlNotationPtr nota, xmlBufferPtr buf) {
- xmlDumpNotationDecl(buf, nota);
+xmlDumpNotationDeclScan(void *nota, void *buf,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota);
}
/**
xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
if ((buf == NULL) || (table == NULL))
return;
- xmlHashScan(table, (xmlHashScanner) xmlDumpNotationDeclScan, buf);
+ xmlHashScan(table, xmlDumpNotationDeclScan, buf);
}
#endif /* LIBXML_OUTPUT_ENABLED */
* DICT_FREE:
* @str: a string
*
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
* current scope
*/
#define DICT_FREE(str) \
return(ret);
}
+static void
+xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFreeID((xmlIDPtr) id);
+}
+
/**
* xmlFreeIDTable:
* @table: An id table
*/
void
xmlFreeIDTable(xmlIDTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
+ xmlHashFree(table, xmlFreeIDTableEntry);
}
/**
return(-1);
}
- xmlHashRemoveEntry(table, ID, (xmlHashDeallocator) xmlFreeID);
+ xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry);
xmlFree(ID);
attr->atype = 0;
return(0);
}
/**
- * xmlFreeRefList:
+ * xmlFreeRefTableEntry:
* @list_ref: A list of references.
*
* Deallocate the memory used by a list of references
*/
static void
-xmlFreeRefList(xmlListPtr list_ref) {
+xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlListPtr list_ref = (xmlListPtr) payload;
if (list_ref == NULL) return;
xmlListDelete(list_ref);
}
* Returns 0 to abort the walk or 1 to continue
*/
static int
-xmlWalkRemoveRef(const void *data, const void *user)
+xmlWalkRemoveRef(const void *data, void *user)
{
xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
*/
void
xmlFreeRefTable(xmlRefTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeRefList);
+ xmlHashFree(table, xmlFreeRefTableEntry);
}
/**
/*If the list is empty then remove the list entry in the hash */
if (xmlListEmpty(ref_list))
- xmlHashUpdateEntry(table, ID, NULL, (xmlHashDeallocator)
- xmlFreeRefList);
+ xmlHashUpdateEntry(table, ID, NULL, xmlFreeRefTableEntry);
xmlFree(ID);
return(0);
}
}
static void
-xmlValidateAttributeIdCallback(xmlAttributePtr attr, int *count,
- const xmlChar* name ATTRIBUTE_UNUSED) {
+xmlValidateAttributeIdCallback(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlAttributePtr attr = (xmlAttributePtr) payload;
+ int *count = (int *) data;
if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
}
nbId = 0;
if (doc->intSubset != NULL) {
table = (xmlAttributeTablePtr) doc->intSubset->attributes;
- xmlHashScan3(table, NULL, NULL, attr->elem, (xmlHashScanner)
+ xmlHashScan3(table, NULL, NULL, attr->elem,
xmlValidateAttributeIdCallback, &nbId);
}
}
}
}
+ /*
+ * Casting ns to xmlAttrPtr is wrong. We'd need separate functions
+ * xmlAddID and xmlAddRef for namespace declarations, but it makes
+ * no practical sense to use ID types anyway.
+ */
+#if 0
/* Validity Constraint: ID uniqueness */
if (attrDecl->atype == XML_ATTRIBUTE_ID) {
if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
ret = 0;
}
+#endif
/* Validity Constraint: Notation Attributes */
if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
case XML_TEXT_NODE:
if (xmlIsBlankNode(cur))
break;
+ /* Falls through. */
case XML_CDATA_SECTION_NODE:
case XML_ENTITY_REF_NODE:
strcat(buf, "CDATA");
xmlElementPtr elemDecl;
/*
- * Check the new element agaisnt the content model of the new elem.
+ * Check the new element against the content model of the new elem.
*/
if (state->elemDecl != NULL) {
elemDecl = state->elemDecl;
xmlElementPtr elemDecl;
/*
- * Check the new element agaisnt the content model of the new elem.
+ * Check the new element against the content model of the new elem.
*/
if (state->elemDecl != NULL) {
elemDecl = state->elemDecl;
xmlElementPtr elemDecl;
/*
- * Check the new element agaisnt the content model of the new elem.
+ * Check the new element against the content model of the new elem.
*/
if (state->elemDecl != NULL) {
elemDecl = state->elemDecl;
* Returns 0 to abort the walk or 1 to continue
*/
static int
-xmlWalkValidateList(const void *data, const void *user)
+xmlWalkValidateList(const void *data, void *user)
{
xmlValidateMemoPtr memo = (xmlValidateMemoPtr)user;
xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
*
*/
static void
-xmlValidateCheckRefCallback(xmlListPtr ref_list, xmlValidCtxtPtr ctxt,
- const xmlChar *name) {
+xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
+ xmlListPtr ref_list = (xmlListPtr) payload;
+ xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
xmlValidateMemo memo;
if (ref_list == NULL)
table = (xmlRefTablePtr) doc->refs;
ctxt->doc = doc;
ctxt->valid = 1;
- xmlHashScan(table, (xmlHashScanner) xmlValidateCheckRefCallback, ctxt);
+ xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
ctxt->finishDtd = save;
return(ctxt->valid);
}
static void
-xmlValidateNotationCallback(xmlEntityPtr cur, xmlValidCtxtPtr ctxt,
+xmlValidateNotationCallback(void *payload, void *data,
const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlEntityPtr cur = (xmlEntityPtr) payload;
+ xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
if (cur == NULL)
return;
if (cur->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
}
static void
-xmlValidateAttributeCallback(xmlAttributePtr cur, xmlValidCtxtPtr ctxt,
- const xmlChar *name ATTRIBUTE_UNUSED) {
+xmlValidateAttributeCallback(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlAttributePtr cur = (xmlAttributePtr) payload;
+ xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
int ret;
xmlDocPtr doc;
xmlElementPtr elem = NULL;
dtd = doc->intSubset;
if ((dtd != NULL) && (dtd->attributes != NULL)) {
table = (xmlAttributeTablePtr) dtd->attributes;
- xmlHashScan(table, (xmlHashScanner) xmlValidateAttributeCallback, ctxt);
+ xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
}
if ((dtd != NULL) && (dtd->entities != NULL)) {
entities = (xmlEntitiesTablePtr) dtd->entities;
- xmlHashScan(entities, (xmlHashScanner) xmlValidateNotationCallback,
- ctxt);
+ xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
}
dtd = doc->extSubset;
if ((dtd != NULL) && (dtd->attributes != NULL)) {
table = (xmlAttributeTablePtr) dtd->attributes;
- xmlHashScan(table, (xmlHashScanner) xmlValidateAttributeCallback, ctxt);
+ xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
}
if ((dtd != NULL) && (dtd->entities != NULL)) {
entities = (xmlEntitiesTablePtr) dtd->entities;
- xmlHashScan(entities, (xmlHashScanner) xmlValidateNotationCallback,
- ctxt);
+ xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
}
return(ctxt->valid);
}
*
* Handle an XInclude error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar *extra)
{
*
* Emit an XInclude warning.
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar *extra)
{
* Inplements the merge of one entity
*/
static void
-xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data,
- xmlChar *name ATTRIBUTE_UNUSED) {
+xmlXIncludeMergeEntity(void *payload, void *vdata,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlEntityPtr ent = (xmlEntityPtr) payload;
+ xmlXIncludeMergeDataPtr data = (xmlXIncludeMergeDataPtr) vdata;
xmlEntityPtr ret, prev;
xmlDocPtr doc;
xmlXIncludeCtxtPtr ctxt;
data.doc = doc;
xmlHashScan((xmlHashTablePtr) source->entities,
- (xmlHashScanner) xmlXIncludeMergeEntity, &data);
+ xmlXIncludeMergeEntity, &data);
}
source = from->extSubset;
if ((source != NULL) && (source->entities != NULL)) {
if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
(!xmlStrEqual(target->SystemID, source->SystemID))) {
xmlHashScan((xmlHashTablePtr) source->entities,
- (xmlHashScanner) xmlXIncludeMergeEntity, &data);
+ xmlXIncludeMergeEntity, &data);
}
}
return(0);
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
#include "libxml.h"
#include <string.h>
+#include <stddef.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#include <zlib.h>
#endif
-#ifdef HAVE_LZMA_H
+#ifdef LIBXML_LZMA_ENABLED
#include <lzma.h>
#endif
-#if defined(WIN32) || defined(_WIN32)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <winnls.h> /* for CP_UTF8 */
#endif
-/* Figure a portable way to know if a file is a directory. */
-#ifndef HAVE_STAT
-# ifdef HAVE__STAT
- /* MS C library seems to define stat and _stat. The definition
- is identical. Still, mapping them to each other causes a warning. */
-# ifndef _MSC_VER
-# define stat(x,y) _stat(x,y)
-# endif
-# define HAVE_STAT
-# endif
-#else
-# ifdef HAVE__STAT
-# if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
-# define stat _stat
-# endif
-# endif
-#endif
-#ifdef HAVE_STAT
-# ifndef S_ISDIR
-# ifdef _S_ISDIR
-# define S_ISDIR(x) _S_ISDIR(x)
-# else
-# ifdef S_IFDIR
-# ifndef S_IFMT
-# ifdef _S_IFMT
-# define S_IFMT _S_IFMT
-# endif
-# endif
-# ifdef S_IFMT
-# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-# endif
-# endif
+#ifndef S_ISDIR
+# ifdef _S_ISDIR
+# define S_ISDIR(x) _S_ISDIR(x)
+# elif defined(S_IFDIR)
+# ifdef S_IFMT
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# elif defined(_S_IFMT)
+# define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
# endif
# endif
#endif
return fd;
}
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
static gzFile
xmlWrapGzOpenUtf8(const char *path, const char *mode)
{
*
*/
static int
-xmlWrapStatUtf8(const char *path,struct stat *info)
-{
-#ifdef HAVE_STAT
+xmlWrapStatUtf8(const char *path, struct _stat *info) {
int retval = -1;
wchar_t *wPath;
wPath = __xmlIOWin32UTF8ToWChar(path);
- if (wPath)
- {
- retval = _wstat(wPath,info);
+ if (wPath) {
+ retval = _wstat(wPath, info);
xmlFree(wPath);
}
/* maybe path in native encoding */
if(retval < 0)
- retval = stat(path,info);
+ retval = _stat(path, info);
return retval;
-#else
- return -1;
-#endif
-}
-
-/**
- * xmlWrapOpenNative:
- * @path: the path
- * @mode: type of access (0 - read, 1 - write)
- *
- * function opens the file specified by @path
- *
- */
-static FILE*
-xmlWrapOpenNative(const char *path,int mode)
-{
- return fopen(path,mode ? "wb" : "rb");
-}
-
-/**
- * xmlWrapStatNative:
- * @path: the path
- * @info: structure that stores results
- *
- * function obtains information about the file or directory
- *
- */
-static int
-xmlWrapStatNative(const char *path,struct stat *info)
-{
-#ifdef HAVE_STAT
- return stat(path,info);
-#else
- return -1;
-#endif
-}
-
-typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s);
-static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative;
-typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode);
-static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative;
-#ifdef HAVE_ZLIB_H
-typedef gzFile (* xmlWrapGzOpenFunc) (const char *f, const char *mode);
-static xmlWrapGzOpenFunc xmlWrapGzOpen = gzopen;
-#endif
-/**
- * xmlInitPlatformSpecificIo:
- *
- * Initialize platform specific features.
- */
-static void
-xmlInitPlatformSpecificIo(void)
-{
- static int xmlPlatformIoInitialized = 0;
- OSVERSIONINFO osvi;
-
- if(xmlPlatformIoInitialized)
- return;
-
- osvi.dwOSVersionInfoSize = sizeof(osvi);
-
- if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
- xmlWrapStat = xmlWrapStatUtf8;
- xmlWrapOpen = xmlWrapOpenUtf8;
-#ifdef HAVE_ZLIB_H
- xmlWrapGzOpen = xmlWrapGzOpenUtf8;
-#endif
- } else {
- xmlWrapStat = xmlWrapStatNative;
- xmlWrapOpen = xmlWrapOpenNative;
-#ifdef HAVE_ZLIB_H
- xmlWrapGzOpen = gzopen;
-#endif
- }
-
- xmlPlatformIoInitialized = 1;
- return;
}
#endif
xmlCheckFilename (const char *path)
{
#ifdef HAVE_STAT
+#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
+ struct _stat stat_buffer;
+#else
struct stat stat_buffer;
+#endif
#endif
if (path == NULL)
return(0);
(path[3] == '\\') )
return 1;
- if (xmlWrapStat(path, &stat_buffer) == -1)
+ if (xmlWrapStatUtf8(path, &stat_buffer) == -1)
return 0;
#else
if (stat(path, &stat_buffer) == -1)
}
/**
- * xmlNop:
+ * xmlInputReadCallbackNop:
*
- * No Operation function, does nothing, no input
+ * No Operation xmlInputReadCallback function, does nothing.
*
* Returns zero
*/
int
-xmlNop(void) {
+xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED,
+ char *buffer ATTRIBUTE_UNUSED,
+ int len ATTRIBUTE_UNUSED) {
return(0);
}
xmlFdRead (void * context, char * buffer, int len) {
int ret;
- ret = read((int) (long) context, &buffer[0], len);
+ ret = read((int) (ptrdiff_t) context, &buffer[0], len);
if (ret < 0) xmlIOErr(0, "read()");
return(ret);
}
int ret = 0;
if (len > 0) {
- ret = write((int) (long) context, &buffer[0], len);
+ ret = write((int) (ptrdiff_t) context, &buffer[0], len);
if (ret < 0) xmlIOErr(0, "write()");
}
return(ret);
static int
xmlFdClose (void * context) {
int ret;
- ret = close((int) (long) context);
+ ret = close((int) (ptrdiff_t) context);
if (ret < 0) xmlIOErr(0, "close()");
return(ret);
}
#endif
}
+ /* Do not check DDNAME on zOS ! */
+#if !defined(__MVS__)
if (!xmlCheckFilename(path))
return(NULL);
+#endif
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- fd = xmlWrapOpen(path, 0);
+ fd = xmlWrapOpenUtf8(path, 0);
#else
fd = fopen(path, "r");
#endif /* WIN32 */
return(NULL);
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- fd = xmlWrapOpen(path, 1);
+ fd = xmlWrapOpenUtf8(path, 1);
+#elif(__MVS__)
+ fd = fopen(path, "w");
#else
- fd = fopen(path, "wb");
+ fd = fopen(path, "wb");
#endif /* WIN32 */
- if (fd == NULL) xmlIOErr(0, path);
+ if (fd == NULL) xmlIOErr(0, path);
return((void *) fd);
}
#endif /* LIBXML_OUTPUT_ENABLED */
}
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
/************************************************************************
* *
* I/O for compressed file accesses *
return(NULL);
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- fd = xmlWrapGzOpen(path, "rb");
+ fd = xmlWrapGzOpenUtf8(path, "rb");
#else
fd = gzopen(path, "rb");
#endif
return(NULL);
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- fd = xmlWrapGzOpen(path, mode);
+ fd = xmlWrapGzOpenUtf8(path, mode);
#else
fd = gzopen(path, mode);
#endif
*
* Read @len bytes to @buffer from the compressed I/O channel.
*
- * Returns the number of bytes written
+ * Returns the number of bytes read.
*/
static int
xmlGzfileRead (void * context, char * buffer, int len) {
if (ret < 0) xmlIOErr(0, "gzclose()");
return(ret);
}
-#endif /* HAVE_ZLIB_H */
+#endif /* LIBXML_ZLIB_ENABLED */
#ifdef LIBXML_LZMA_ENABLED
/************************************************************************
} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
#define DFLT_WBITS ( -15 )
#define DFLT_MEM_LVL ( 8 )
xmlFreeZMemBuff( buff );
buff = NULL;
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlCreateZMemBuff: %s %d\n",
+ "xmlCreateZMemBuff: %s %d\n",
"Error initializing compression context. ZLIB error:",
z_err );
xmlIOErr(XML_IO_WRITE, (const char *) msg);
else {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlZMemBuffExtend: %s %lu bytes.\n",
+ "xmlZMemBuffExtend: %s %lu bytes.\n",
"Allocation failure extending output buffer to",
- new_size );
+ (unsigned long) new_size );
xmlIOErr(XML_IO_WRITE, (const char *) msg);
}
if ( z_err != Z_OK ) {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlZMemBuffAppend: %s %d %s - %d",
+ "xmlZMemBuffAppend: %s %d %s - %d",
"Compression error while appending",
len, "bytes to buffer. ZLIB error", z_err );
xmlIOErr(XML_IO_WRITE, (const char *) msg);
else {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlZMemBuffGetContent: %s - %d\n",
+ "xmlZMemBuffGetContent: %s - %d\n",
"Error flushing zlib buffers. Error code", z_err );
xmlIOErr(XML_IO_WRITE, (const char *) msg);
}
return ( zlgth );
}
#endif /* LIBXML_OUTPUT_ENABLED */
-#endif /* HAVE_ZLIB_H */
+#endif /* LIBXML_ZLIB_ENABLED */
#ifdef LIBXML_OUTPUT_ENABLED
/**
if ( ctxt->doc_buff != NULL ) {
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ( ctxt->compression > 0 ) {
xmlFreeZMemBuff( ctxt->doc_buff );
}
*/
void *
-xmlIOHTTPOpenW(const char *post_uri, int compression)
+xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED)
{
xmlIOHTTPWriteCtxtPtr ctxt = NULL;
* ** is being used to avoid pushing the data to disk and back.
*/
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ((compression > 0) && (compression <= 9)) {
ctxt->compression = compression;
/* Use gzwrite or fwrite as previously setup in the open call */
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ( ctxt->compression > 0 )
len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
if ( len < 0 ) {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlIOHTTPWrite: %s\n%s '%s'.\n",
+ "xmlIOHTTPWrite: %s\n%s '%s'.\n",
"Error appending to internal buffer.",
"Error sending document to URI",
ctxt->uri );
/* Retrieve the content from the appropriate buffer */
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ( ctxt->compression > 0 ) {
content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
if ( http_content == NULL ) {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
+ "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
"Error retrieving content.\nUnable to",
http_mthd, "data to URI", ctxt->uri );
xmlIOErr(XML_IO_WRITE, (const char *) msg);
else {
xmlChar msg[500];
xmlStrPrintf(msg, 500,
- (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
+ "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
http_mthd, content_lgth,
"bytes to URI", ctxt->uri,
"failed. HTTP return code:", http_rtn );
if (xmlInputCallbackInitialized)
return;
-#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- xmlInitPlatformSpecificIo();
-#endif
-
xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
xmlFileRead, xmlFileClose);
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
xmlGzfileRead, xmlGzfileClose);
-#endif /* HAVE_ZLIB_H */
+#endif /* LIBXML_ZLIB_ENABLED */
#ifdef LIBXML_LZMA_ENABLED
xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
xmlXzfileRead, xmlXzfileClose);
if (xmlOutputCallbackInitialized)
return;
-#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
- xmlInitPlatformSpecificIo();
-#endif
-
xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
xmlFileWrite, xmlFileClose);
uncompressed ones except opening if existing then closing
and saving with same compression ratio ... a pain.
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
xmlGzfileWrite, xmlGzfileClose);
#endif
ret->context = context;
ret->readcallback = xmlInputCallbackTable[i].readcallback;
ret->closecallback = xmlInputCallbackTable[i].closecallback;
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
(strcmp(URI, "-") != 0)) {
#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
int i = 0;
void *context = NULL;
char *unescaped = NULL;
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
int is_file_uri = 1;
#endif
puri = xmlParseURI(URI);
if (puri != NULL) {
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ((puri->scheme != NULL) &&
(!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
is_file_uri = 0;
* try with an unescaped version of the URI
*/
if (unescaped != NULL) {
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
context = xmlGzfileOpenW(unescaped, compression);
if (context != NULL) {
for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
(xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
-#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
+#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
/* Need to pass compression parameter into HTTP open calls */
if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
context = xmlIOHTTPOpenW(unescaped, compression);
* filename
*/
if (context == NULL) {
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
context = xmlGzfileOpenW(URI, compression);
if (context != NULL) {
for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
(xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
-#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
+#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
/* Need to pass compression parameter into HTTP open calls */
if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
context = xmlIOHTTPOpenW(URI, compression);
if (buffer == NULL) return(NULL);
- ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
- xmlBufferWrite,
- (xmlOutputCloseCallback)
- NULL, (void *) buffer, encoder);
+ ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
+ encoder);
return(ret);
}
ret = xmlAllocParserInputBuffer(enc);
if (ret != NULL) {
- ret->context = (void *) (long) fd;
+ ret->context = (void *) (ptrdiff_t) fd;
ret->readcallback = xmlFdRead;
ret->closecallback = xmlFdClose;
}
xmlParserInputBufferPtr ret;
int errcode;
- if (size <= 0) return(NULL);
+ if (size < 0) return(NULL);
if (mem == NULL) return(NULL);
ret = xmlAllocParserInputBuffer(enc);
if (ret != NULL) {
ret->context = (void *) mem;
- ret->readcallback = (xmlInputReadCallback) xmlNop;
+ ret->readcallback = xmlInputReadCallbackNop;
ret->closecallback = NULL;
errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
if (errcode != 0) {
xmlCharEncoding enc) {
xmlParserInputBufferPtr ret;
- if (size <= 0) return(NULL);
+ if (size < 0) return(NULL);
if (mem == NULL) return(NULL);
ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
ret = xmlAllocOutputBufferInternal(encoder);
if (ret != NULL) {
- ret->context = (void *) (long) fd;
+ ret->context = (void *) (ptrdiff_t) fd;
ret->writecallback = xmlFdWrite;
ret->closecallback = NULL;
}
if (filename == NULL) return(NULL);
-#if defined(WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
# define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
#else
# define IS_XMLPGD_SEP(ch) (ch=='/')
int code,
xmlNodePtr node,
const char *msg,
- const char *extra);
+ const char *extra) LIBXML_ATTR_FORMAT(4,0);
#endif
#ifdef __cplusplus
}
#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
/ ALIGN_SIZE ) * ALIGN_SIZE)
+#define MAX_SIZE_T ((size_t)-1)
-#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
+#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
TEST_POINT
+ if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlMallocLoc : Unsigned overflow\n");
+ xmlMemoryDump();
+ return(NULL);
+ }
+
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
if (!p) {
/**
* xmlMallocAtomicLoc:
- * @size: an int specifying the size in byte to allocate.
+ * @size: an unsigned int specifying the size in byte to allocate.
* @file: the file name or NULL
* @line: the line number
*
TEST_POINT
+ if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlMallocAtomicLoc : Unsigned overflow\n");
+ xmlMemoryDump();
+ return(NULL);
+ }
+
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
if (!p) {
xmlGenericError(xmlGenericErrorContext,
- "xmlMallocLoc : Out of free space\n");
+ "xmlMallocAtomicLoc : Out of free space\n");
xmlMemoryDump();
return(NULL);
}
#endif
xmlMutexUnlock(xmlMemMutex);
+ if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlReallocLoc : Unsigned overflow\n");
+ xmlMemoryDump();
+ return(NULL);
+ }
+
tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
if (!tmp) {
free(p);
error:
xmlGenericError(xmlGenericErrorContext,
- "xmlMemFree(%lX) error\n", (unsigned long) ptr);
+ "xmlMemFree(%p) error\n", ptr);
xmlMallocBreakpoint();
return;
}
if (!xmlMemInitialized) xmlInitMemory();
TEST_POINT
+ if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlMemStrdupLoc : Unsigned overflow\n");
+ xmlMemoryDump();
+ return(NULL);
+ }
+
p = (MEMHDR *) malloc(RESERVE_SIZE+size);
if (!p) {
goto error;
* http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
*/
+/* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
+#if defined(__MVS__)
+#define _UNIX03_SOURCE
+#endif
+
#define IN_LIBXML
#include "libxml.h"
#endif /* HAVE_SHLLOAD */
#endif /* ! HAVE_DLOPEN */
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/*
static int
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
{
+XML_IGNORE_PEDANTIC_WARNINGS
#ifdef _WIN32_WCE
/*
* GetProcAddressA seems only available on WinCE
*symbol = GetProcAddress(handle, name);
#endif
return (NULL == *symbol) ? -1 : 0;
+XML_POP_WARNINGS
}
#endif /* _WIN32 */
xmlNodePtr faketext;/* fake xmlNs chld */
int preserve;/* preserve the resulting document */
xmlBufPtr buffer; /* used to return const xmlChar * */
- xmlDictPtr dict; /* the context dictionnary */
+ xmlDictPtr dict; /* the context dictionary */
/* entity stack when traversing entities content */
xmlNodePtr ent; /* Current Entity Ref Node */
* DICT_FREE:
* @str: a string
*
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
* current scope
*/
#define DICT_FREE(str) \
}
}
+static void
+xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFreeID((xmlIDPtr) id);
+}
+
/**
* xmlTextReaderFreeIDTable:
* @table: An id table
*/
static void
xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
- xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
+ xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
}
/**
if (xmlTextReaderExpand(reader) == NULL) {
return NULL;
}
- doc = reader->doc;
+ doc = reader->node->doc;
buff = xmlBufferCreate();
for (cur_node = reader->node->children; cur_node != NULL;
cur_node = cur_node->next) {
+ /* XXX: Why is the node copied? */
node = xmlDocCopyNode(cur_node, doc, 1);
buff2 = xmlBufferCreate();
if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
xmlDocPtr doc;
node = reader->node;
- doc = reader->doc;
+ doc = node->doc;
if (xmlTextReaderExpand(reader) == NULL) {
return NULL;
}
+ /* XXX: Why is the node copied? */
if (node->type == XML_DTD_NODE) {
node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
} else {
/* if reader->node->next is NULL mean no subtree for current node,
so need to move to sibling of parent node if present */
- if ((reader->node->type == XML_ELEMENT_NODE) ||
- (reader->node->type == XML_ATTRIBUTE_NODE)) {
- reader->state = XML_TEXTREADER_BACKTRACK;
- /* This will move to parent if present */
- xmlTextReaderRead(reader);
- }
+ reader->state = XML_TEXTREADER_BACKTRACK;
+ /* This will move to parent if present */
+ xmlTextReaderRead(reader);
}
if (reader->node->next != 0) {
ret->ctxt->dictNames = 1;
ret->allocs = XML_TEXTREADER_CTXT;
/*
- * use the parser dictionnary to allocate all elements and attributes names
+ * use the parser dictionary to allocate all elements and attributes names
*/
ret->ctxt->docdict = 1;
ret->dict = ret->ctxt->dict;
* Reference:
* https://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
*
- * Returns the xmlNodeType of the current node or -1 in case of error
+ * Returns the xmlReaderTypes of the current node or -1 in case of error
*/
int
xmlTextReaderNodeType(xmlTextReaderPtr reader) {
* pattern. The caller must also use xmlTextReaderCurrentDoc() to
* keep an handle on the resulting document once parsing has finished
*
- * Returns a positive number in case of success and -1 in case of error
+ * Returns a non-negative number in case of success and -1 in case of error
*/
int
xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
}
#ifdef LIBXML_SCHEMAS_ENABLED
-static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
+static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
static void XMLCDECL
-xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
+xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static void XMLCDECL
-xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
+xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
+
+static void XMLCDECL
+xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
+
+static void XMLCDECL
+xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
static void XMLCDECL
xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
}
}
-static void XMLCDECL
+static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderError(void *ctxt, const char *msg, ...)
{
va_list ap;
}
-static void XMLCDECL
+static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderWarning(void *ctxt, const char *msg, ...)
{
va_list ap;
reader->ctxt->linenumbers = 1;
reader->ctxt->dictNames = 1;
/*
- * use the parser dictionnary to allocate all elements and attributes names
+ * use the parser dictionary to allocate all elements and attributes names
*/
reader->ctxt->docdict = 1;
reader->ctxt->parseMode = XML_PARSE_READER;
* @arg: the user argument
* @msg: the message
* @severity: the severity of the error
- * @locator: a locator indicating where the error occured
+ * @locator: a locator indicating where the error occurred
*
* Signature of an error callback from a reader parser
*/
xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
xmlRegStatePtr to, xmlRegAtomPtr atom) {
xmlRegStatePtr end;
+ int nullable = 0;
if (atom == NULL) {
ERROR("genrate transition: atom == NULL");
if (xmlRegAtomPush(ctxt, atom) < 0) {
return(-1);
}
+ if ((atom->quant == XML_REGEXP_QUANT_RANGE) &&
+ (atom->min == 0) && (atom->max > 0)) {
+ nullable = 1;
+ atom->min = 1;
+ if (atom->max == 1)
+ atom->quant = XML_REGEXP_QUANT_OPT;
+ }
xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
ctxt->state = end;
switch (atom->quant) {
xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1);
break;
case XML_REGEXP_QUANT_RANGE:
-#if DV_test
- if (atom->min == 0) {
+ if (nullable)
xmlFAGenerateEpsilonTransition(ctxt, from, to);
- }
-#endif
break;
default:
break;
break;
case XML_REGEXP_NOTSPACE:
neg = !neg;
+ /* Falls through. */
case XML_REGEXP_ANYSPACE:
ret = ((codepoint == '\n') || (codepoint == '\r') ||
(codepoint == '\t') || (codepoint == ' '));
break;
case XML_REGEXP_NOTINITNAME:
neg = !neg;
+ /* Falls through. */
case XML_REGEXP_INITNAME:
ret = (IS_LETTER(codepoint) ||
(codepoint == '_') || (codepoint == ':'));
break;
case XML_REGEXP_NOTNAMECHAR:
neg = !neg;
+ /* Falls through. */
case XML_REGEXP_NAMECHAR:
ret = (IS_LETTER(codepoint) || IS_DIGIT(codepoint) ||
(codepoint == '.') || (codepoint == '-') ||
break;
case XML_REGEXP_NOTDECIMAL:
neg = !neg;
+ /* Falls through. */
case XML_REGEXP_DECIMAL:
ret = xmlUCSIsCatNd(codepoint);
break;
case XML_REGEXP_REALCHAR:
neg = !neg;
+ /* Falls through. */
case XML_REGEXP_NOTREALCHAR:
ret = xmlUCSIsCatP(codepoint);
if (ret == 0)
xmlFree(exec->errString);
exec->errString = xmlStrdup(value);
exec->errState = exec->state;
- memcpy(exec->errCounts, exec->counts,
- exec->comp->nbCounters * sizeof(int));
+ if (exec->comp->nbCounters)
+ memcpy(exec->errCounts, exec->counts,
+ exec->comp->nbCounters * sizeof(int));
}
/*
}
NEXT;
xmlFAParseCharProp(ctxt);
- ctxt->atom->neg = 1;
+ if (ctxt->atom != NULL)
+ ctxt->atom->neg = 1;
if (CUR != '}') {
ERROR("Expecting '}'");
return;
return;
}
len = 1;
- } else if ((cur != 0x5B) && (cur != 0x5D)) {
+ } else if ((cur != '\0') && (cur != 0x5B) && (cur != 0x5D)) {
end = CUR_SCHAR(ctxt->cur, len);
} else {
ERROR("Expecting the end of a char range");
return;
}
- NEXTL(len);
+
/* TODO check that the values are acceptable character ranges for XML */
if (end < start) {
ERROR("End of range is before start of range");
} else {
+ NEXTL(len);
xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
XML_REGEXP_CHARVAL, start, end, NULL);
}
/**
* xmlExpNewCtxt:
* @maxNodes: the maximum number of nodes
- * @dict: optional dictionnary to use internally
+ * @dict: optional dictionary to use internally
*
* Creates a new context for manipulating expressions
*
return(NULL);
}
/*
- * check the string is in the dictionnary, if yes use an interned
+ * check the string is in the dictionary, if yes use an interned
* copy, otherwise we know it's not an acceptable input
*/
input = xmlDictExists(ctxt->dict, str, len);
cur->encoding = BAD_CAST ctxt->encoding;
} else if (cur->encoding != NULL) {
encoding = cur->encoding;
- } else if (cur->charset != XML_CHAR_ENCODING_UTF8) {
- encoding = (const xmlChar *)
- xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
}
if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
if (cur->properties != NULL)
xhtmlAttrListDumpOutput(ctxt, cur->properties);
- if ((cur->type == XML_ELEMENT_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->parent == (xmlNodePtr) cur->doc) &&
- xmlStrEqual(cur->name, BAD_CAST"head") &&
- xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
-
- tmp = cur->children;
- while (tmp != NULL) {
- if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
- xmlChar *httpequiv;
-
- httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
- if (httpequiv != NULL) {
- if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
- xmlFree(httpequiv);
- break;
- }
- xmlFree(httpequiv);
- }
- }
- tmp = tmp->next;
- }
- if (tmp == NULL)
- addmeta = 1;
- }
+ if ((cur->type == XML_ELEMENT_NODE) &&
+ (cur->parent != NULL) &&
+ (cur->parent->parent == (xmlNodePtr) cur->doc) &&
+ xmlStrEqual(cur->name, BAD_CAST"head") &&
+ xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
+
+ tmp = cur->children;
+ while (tmp != NULL) {
+ if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
+ xmlChar *httpequiv;
+
+ httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
+ if (httpequiv != NULL) {
+ if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
+ xmlFree(httpequiv);
+ break;
+ }
+ xmlFree(httpequiv);
+ }
+ }
+ tmp = tmp->next;
+ }
+ if (tmp == NULL)
+ addmeta = 1;
+ }
if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) {
if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
xmlBufAdd(buf, BAD_CAST "&", 5);
cur++;
base = cur;
- } else if ((*cur >= 0x80) && ((doc == NULL) ||
- (doc->encoding == NULL))) {
+ } else if ((*cur >= 0x80) && (cur[1] != 0) &&
+ ((doc == NULL) || (doc->encoding == NULL))) {
/*
* We assume we have UTF-8 content.
*/
xmlBufAdd(buf, base, cur - base);
if (*cur < 0xC0) {
xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
- if (doc != NULL)
- doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
xmlSerializeHexCharRef(tmp, *cur);
xmlBufAdd(buf, (xmlChar *) tmp, -1);
cur++;
val <<= 6;
val |= (cur[1]) & 0x3F;
l = 2;
- } else if (*cur < 0xF0) {
+ } else if ((*cur < 0xF0) && (cur [2] != 0)) {
val = (cur[0]) & 0x0F;
val <<= 6;
val |= (cur[1]) & 0x3F;
val <<= 6;
val |= (cur[2]) & 0x3F;
l = 3;
- } else if (*cur < 0xF8) {
+ } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
val = (cur[0]) & 0x07;
val <<= 6;
val |= (cur[1]) & 0x3F;
}
if ((l == 1) || (!IS_CHAR(val))) {
xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
- if (doc != NULL)
- doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
-
xmlSerializeHexCharRef(tmp, *cur);
xmlBufAdd(buf, (xmlChar *) tmp, -1);
cur++;
return(-1);
}
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
if (cur->compression < 0) cur->compression = xmlGetCompressMode();
#endif
/*
* but is done here due to performance. Move it to an other layer
* is schema construction via an API is implemented.
*/
+
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
/*
* Macros for attribute uses.
*/
-#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
+#define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
struct _xmlSchemaAbstractCtxt {
int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
+ void *dummy; /* Fix alignment issues */
};
typedef struct _xmlSchemaBucket xmlSchemaBucket;
typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
struct _xmlSchemaBasicItem {
xmlSchemaTypeType type;
+ void *dummy; /* Fix alignment issues */
};
/**
xmlAutomataStatePtr end;
xmlAutomataStatePtr state;
- xmlDictPtr dict; /* dictionnary for interned string names */
+ xmlDictPtr dict; /* dictionary for interned string names */
xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
int options;
xmlSchemaValidCtxtPtr vctxt;
static void
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
- const char *message);
+ const char *message) LIBXML_ATTR_FORMAT(3,0);
static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
xmlSchemaTypePtr type,
*buf = xmlStrcat(*buf, BAD_CAST "'");
FREE_AND_NULL(str);
}
+ /* Falls through. */
default:
named = 0;
}
}
FREE_AND_NULL(str)
- return (*buf);
+ return (xmlEscapeFormatString(buf));
}
/**
*
* Handle a parser error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
{
*
* Handle a parser error
*/
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
xmlNodePtr child, int error,
const char *msg, const xmlChar * str1, const xmlChar * str2)
*
* Handle a parser error
*/
-static void
+static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
const xmlChar * strData1, const xmlChar * strData2,
const xmlChar * strData3, const char *msg, const xmlChar * str1,
extra);
}
-static void
+static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,
const char *msg, const xmlChar *str)
{
#define WXS_ERROR_TYPE_ERROR 1
#define WXS_ERROR_TYPE_WARNING 2
/**
- * xmlSchemaErr3:
+ * xmlSchemaErr4Line:
* @ctxt: the validation context
- * @node: the context node
+ * @errorLevel: the error level
* @error: the error code
+ * @node: the context node
+ * @line: the line number
* @msg: the error message
* @str1: extra data
* @str2: extra data
* @str3: extra data
+ * @str4: extra data
*
* Handle a validation error
*/
-static void
+static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
xmlErrorLevel errorLevel,
int error, xmlNodePtr node, int line, const char *msg,
*
* Handle a validation error
*/
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
msg, str1, str2, str3, NULL);
}
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2,
msg, str1, str2, str3, str4);
}
-static void
+static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
int error, xmlNodePtr node, const char *msg,
const xmlChar *str1, const xmlChar *str2)
/*
* Don't try to format other nodes than element and
* attribute nodes.
- * Play save and return an empty string.
+ * Play safe and return an empty string.
*/
*msg = xmlStrdup(BAD_CAST "");
return(*msg);
TODO
return (NULL);
}
+
+ /*
+ * xmlSchemaFormatItemForReport() also returns an escaped format
+ * string, so do this before calling it below (in the future).
+ */
+ xmlEscapeFormatString(msg);
+
/*
* VAL TODO: The output of the given schema component is currently
* disabled.
return (*msg);
}
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
const char *message,
if (actxt == NULL)
return;
- msg = xmlStrdup(BAD_CAST "Internal error: ");
- msg = xmlStrcat(msg, BAD_CAST funcName);
- msg = xmlStrcat(msg, BAD_CAST ", ");
+ msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
msg = xmlStrcat(msg, BAD_CAST message);
msg = xmlStrcat(msg, BAD_CAST ".\n");
if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
- xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
- (const char *) msg, str1, str2);
-
+ xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
+ (const char *) msg, (const xmlChar *) funcName, str1, str2);
else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
- xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
- (const char *) msg, str1, str2);
+ xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
+ (const char *) msg, (const xmlChar *) funcName, str1, str2);
FREE_AND_NULL(msg)
}
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
const char *funcName,
const char *message)
}
#if 0
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
const char *funcName,
const char *message,
}
#endif
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
FREE_AND_NULL(msg)
}
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
xmlParserErrors error,
xmlSchemaPSVIIDCNodePtr idcNode,
msg = xmlStrcat(msg, BAD_CAST " '");
if (type->builtInType != 0) {
msg = xmlStrcat(msg, BAD_CAST "xs:");
- msg = xmlStrcat(msg, type->name);
- } else
- msg = xmlStrcat(msg,
- xmlSchemaFormatQName(&str,
- type->targetNamespace, type->name));
+ str = xmlStrdup(type->name);
+ } else {
+ const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
+ if (!str)
+ str = xmlStrdup(qName);
+ }
+ msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
msg = xmlStrcat(msg, BAD_CAST "'");
FREE_AND_NULL(str);
}
FREE_AND_NULL(msg)
}
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
str = xmlStrcat(str, BAD_CAST ", ");
}
str = xmlStrcat(str, BAD_CAST " ).\n");
- msg = xmlStrcat(msg, BAD_CAST str);
+ msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
FREE_AND_NULL(str)
} else
msg = xmlStrcat(msg, BAD_CAST "\n");
xmlFree(msg);
}
-static void
+static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
xmlParserErrors error,
xmlNodePtr node,
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
if (refTypeStr == NULL)
refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
- xmlSchemaPErrExt(ctxt, ownerElem, error,
+ xmlSchemaPErrExt(ctxt, ownerElem, error,
NULL, NULL, NULL,
"%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
"%s.\n", BAD_CAST des, BAD_CAST name,
*
* Reports an error during parsing.
*/
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr item,
*
* Reports an error during parsing.
*/
-static void
+static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr item,
*
* Reports an attribute use error during parsing.
*/
-static void
+static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlNodePtr node,
* Reports a simple type validation error.
* TODO: Should this report the value of an element as well?
*/
-static void
+static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
xmlParserErrors error,
xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
msg = xmlStrcat(msg, BAD_CAST " '");
if (type->builtInType != 0) {
msg = xmlStrcat(msg, BAD_CAST "xs:");
- msg = xmlStrcat(msg, type->name);
- } else
- msg = xmlStrcat(msg,
- xmlSchemaFormatQName(&str,
- type->targetNamespace, type->name));
+ str = xmlStrdup(type->name);
+ } else {
+ const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
+ if (!str)
+ str = xmlStrdup(qName);
+ }
+ msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
msg = xmlStrcat(msg, BAD_CAST "'.");
FREE_AND_NULL(str);
}
"valid.");
}
if (expected) {
+ xmlChar *expectedEscaped = xmlCharStrdup(expected);
msg = xmlStrcat(msg, BAD_CAST " Expected is '");
- msg = xmlStrcat(msg, BAD_CAST expected);
+ msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
+ FREE_AND_NULL(expectedEscaped);
msg = xmlStrcat(msg, BAD_CAST "'.\n");
} else
msg = xmlStrcat(msg, BAD_CAST "\n");
xmlFree(bucket);
}
+static void
+xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
+{
+ xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
+}
+
static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
int type, const xmlChar *targetNamespace)
xmlHashFree(schema->idcDef, NULL);
if (schema->schemasImports != NULL)
- xmlHashFree(schema->schemasImports,
- (xmlHashDeallocator) xmlSchemaBucketFree);
+ xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
if (schema->includes != NULL) {
xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
int i;
* Dump the element
*/
static void
-xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
+xmlSchemaElementDump(void *payload, void *data,
const xmlChar * name ATTRIBUTE_UNUSED,
const xmlChar * namespace ATTRIBUTE_UNUSED,
const xmlChar * context ATTRIBUTE_UNUSED)
{
+ xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
+ FILE *output = (FILE *) data;
if (elem == NULL)
return;
#endif
}
+static void
+xmlSchemaTypeDumpEntry(void *type, void *output,
+ const xmlChar *name ATTRIBUTE_UNUSED)
+{
+ xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
+}
+
/**
* xmlSchemaDump:
* @output: the file output
fprintf(output, "\n");
if (schema->annot != NULL)
xmlSchemaAnnotDump(output, schema->annot);
- xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
- output);
- xmlHashScanFull(schema->elemDecl,
- (xmlHashScannerFull) xmlSchemaElementDump, output);
+ xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
+ xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
}
#ifdef DEBUG_IDC_NODE_TABLE
xmlFree(group);
}
+static void
+xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
+{
+ xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
+}
+
static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
xmlSchemaElementPtr head)
*/
if (defValue != NULL)
use->defValue = defValue;
- if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
- use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
+ if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
+ use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
}
check_children:
if (con->pending != NULL)
xmlSchemaItemListFree(con->pending);
if (con->substGroups != NULL)
- xmlHashFree(con->substGroups,
- (xmlHashDeallocator) xmlSchemaSubstGroupFree);
+ xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
if (con->redefs != NULL)
xmlSchemaRedefListFree(con->redefs);
if (con->dict != NULL)
* STATUS: (seems) complete
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
* (1.4.3.2.2.2) "Particle Valid (Extension)"
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
* Validation Rule: Checking complex type subsumption
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
* (3.4.6) Constraints on Complex Type Definition Schema Components
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
* Complex Type Definition Representation OK (src-ct)
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
* STATUS: complete
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
* CLARIFY: (3.2.2)
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
* STATUS: complete
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
* STATUS: TODO
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
* STATUS: complete
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
* STATUS: TODO
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
* STATUS: TODO: subst-groups
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
* TODO: subst-groups
*
* Returns 0 if the constraints are satisfied, a positive
- * error code if not and -1 if an internal error occured.
+ * error code if not and -1 if an internal error occurred.
*/
static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
return (0);
internal_error:
PERROR_INT("xmlSchemaDeriveAndValidateFacets",
- "an error occured");
+ "an error occurred");
return (-1);
}
con->bucket = oldbucket;
con->pending->nbItems = 0;
if (con->substGroups != NULL) {
- xmlHashFree(con->substGroups,
- (xmlHashDeallocator) xmlSchemaSubstGroupFree);
+ xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
con->substGroups = NULL;
}
if (con->redefs != NULL) {
ctxt->ownsConstructor = 0;
}
PERROR_INT2("xmlSchemaParse",
- "An internal error occured");
+ "An internal error occurred");
ctxt->schema = NULL;
return(NULL);
}
* Returns the item, or NULL on internal errors.
*/
static void
-xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
- xmlSchemaValidCtxtPtr vctxt)
+xmlSchemaAugmentIDC(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED)
{
+ xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
+ xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
xmlSchemaIDCAugPtr aidc;
aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
* Creates an augmented IDC definition for the imported schema.
*/
static void
-xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
+xmlSchemaAugmentImportedIDC(void *payload, void *data,
+ const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
+ xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
if (imported->schema->idcDef != NULL) {
- xmlHashScan(imported->schema->idcDef ,
- (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
+ xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
}
}
}
static void
-xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
+xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
const xmlChar * name ATTRIBUTE_UNUSED,
- xmlSchemaElementPtr item,
- xmlSchemaNodeInfoPtr inode)
+ void *transdata, void *inputdata)
{
+ xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
+ xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
inode->decl = item;
#ifdef DEBUG_CONTENT
{
*/
inode->regexCtxt =
xmlRegNewExecCtxt(inode->typeDef->contModel,
- (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
- vctxt);
+ xmlSchemaVContentModelCallback, vctxt);
if (inode->regexCtxt == NULL) {
VERROR_INT("xmlSchemaValidatorPopElem",
"failed to create a regex context");
/*
* Get hold of the still expected content, since a further
- * call to xmlRegExecPushString() will loose this information.
+ * call to xmlRegExecPushString() will lose this information.
*/
xmlRegExecNextValues(inode->regexCtxt,
&nbval, &nbneg, &values[0], &terminal);
* Create the regex context.
*/
regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
- (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
- vctxt);
+ xmlSchemaVContentModelCallback, vctxt);
if (regexCtxt == NULL) {
VERROR_INT("xmlSchemaValidateChildElem",
"failed to create a regex context");
* Augment the IDC definitions for the main schema and all imported ones
* NOTE: main schema is the first in the imported list
*/
- xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
+ xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
+ vctxt);
}
if (vctxt->depth > 0) {
/*
}
if (ret < 0) {
/*
- * VAL TODO: A reader error occured; what to do here?
+ * VAL TODO: A reader error occurred; what to do here?
*/
ret = 1;
goto exit;
* attributes yet.
*/
if (nb_attributes != 0) {
+ int valueLen, k, l;
xmlChar *value;
for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
/*
- * Duplicate the value.
+ * Duplicate the value, changing any & to a literal ampersand.
+ *
+ * libxml2 differs from normal SAX here in that it escapes all ampersands
+ * as & instead of delivering the raw converted string. Changing the
+ * behavior at this point would break applications that use this API, so
+ * we are forced to work around it.
*/
- value = xmlStrndup(attributes[j+3],
- attributes[j+4] - attributes[j+3]);
+ valueLen = attributes[j+4] - attributes[j+3];
+ value = xmlMallocAtomic(valueLen + 1);
+ if (value == NULL) {
+ xmlSchemaVErrMemory(vctxt,
+ "allocating string for decoded attribute",
+ NULL);
+ goto internal_error;
+ }
+ for (k = 0, l = 0; k < valueLen; l++) {
+ if (k < valueLen - 4 &&
+ attributes[j+3][k+0] == '&' &&
+ attributes[j+3][k+1] == '#' &&
+ attributes[j+3][k+2] == '3' &&
+ attributes[j+3][k+3] == '8' &&
+ attributes[j+3][k+4] == ';') {
+ value[l] = '&';
+ k += 5;
+ } else {
+ value[l] = attributes[j+3][k];
+ k++;
+ }
+ }
+ value[l] = '\0';
/*
* TODO: Set the node line.
*/
vctxt->nbIdcNodes = 0;
vctxt->sizeIdcNodes = 0;
}
+
+ if (vctxt->idcKeys != NULL) {
+ int i;
+ for (i = 0; i < vctxt->nbIdcKeys; i++)
+ xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
+ xmlFree(vctxt->idcKeys);
+ vctxt->idcKeys = NULL;
+ vctxt->nbIdcKeys = 0;
+ vctxt->sizeIdcKeys = 0;
+ }
+
/*
* Note that we won't delete the XPath state pool here.
*/
{
if (ctxt == NULL)
return;
- ctxt->serror = serror;
+ ctxt->serror = serror;
ctxt->error = NULL;
ctxt->warning = NULL;
ctxt->errCtxt = ctx;
* Augment the IDC definitions for the main schema and all imported ones
* NOTE: main schema if the first in the imported list
*/
- xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
+ xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
+ vctxt);
return(0);
}
* Daniel Veillard <veillard@redhat.com>
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
long year;
unsigned int mon :4; /* 1 <= mon <= 12 */
unsigned int day :5; /* 1 <= day <= 31 */
- unsigned int hour :5; /* 0 <= hour <= 23 */
+ unsigned int hour :5; /* 0 <= hour <= 24 */
unsigned int min :6; /* 0 <= min <= 59 */
double sec;
unsigned int tz_flag :1; /* is tzo explicitely set? */
xmlSchemaTypesInitialized = 1;
}
+static void
+xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlSchemaFreeType((xmlSchemaTypePtr) type);
+}
+
/**
* xmlSchemaCleanupTypes:
*
xmlFree((xmlSchemaParticlePtr) particle);
xmlSchemaTypeAnyTypeDef->subtypes = NULL;
}
- xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
+ xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
xmlSchemaTypesInitialized = 0;
}
#define VALID_DATE(dt) \
(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
+#define VALID_END_OF_DAY(dt) \
+ ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
+
#define VALID_TIME(dt) \
- (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
- VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
+ (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
+ VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \
+ VALID_TZO(dt->tzo))
#define VALID_DATETIME(dt) \
(VALID_DATE(dt) && VALID_TIME(dt))
return ret;
if (*cur != ':')
return 1;
- if (!VALID_HOUR(value))
+ if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
return 2;
cur++;
if (ret != 0)
return ret;
- if ((!VALID_SEC(dt->sec)) || (!VALID_TZO(dt->tzo)))
+ if (!VALID_TIME(dt))
return 2;
*str = cur;
xmlSchemaWhitespaceValueType ws)
{
int ret;
+ int stringType;
if (facet == NULL)
return(-1);
*/
if (value == NULL)
return(-1);
- ret = xmlRegexpExec(facet->regexp, value);
+ /*
+ * If string-derived type, regexp must be tested on the value space of
+ * the datatype.
+ * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
+ */
+ stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
+ || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
+ ret = xmlRegexpExec(facet->regexp,
+ (stringType && val->value.str) ? val->value.str : value);
if (ret == 1)
return(0);
if (ret == 0)
if ((valType == XML_SCHEMAS_QNAME) ||
(valType == XML_SCHEMAS_NOTATION))
return (0);
- /* No break on purpose. */
+ /* Falls through. */
case XML_SCHEMA_FACET_MAXLENGTH:
case XML_SCHEMA_FACET_MINLENGTH: {
unsigned int len = 0;
* first bytes of @add. Note that if @len < 0 then this is an API error
* and NULL will be returned.
*
- * Returns a new xmlChar *, the original @cur is reallocated if needed
- * and should not be freed
+ * Returns a new xmlChar *, the original @cur is reallocated and should
+ * not be freed.
*/
xmlChar *
return(xmlStrndup(add, len));
size = xmlStrlen(cur);
+ if (size < 0)
+ return(NULL);
ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
int size;
xmlChar *ret;
- if (len < 0)
+ if (len < 0) {
len = xmlStrlen(str2);
+ if (len < 0)
+ return(NULL);
+ }
if ((str2 == NULL) || (len == 0))
return(xmlStrdup(str1));
if (str1 == NULL)
return(xmlStrndup(str2, len));
size = xmlStrlen(str1);
+ if (size < 0)
+ return(NULL);
ret = (xmlChar *) xmlMalloc((size + len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
* encoded in UTF-8 or an encoding with 8bit based chars, we assume
* a termination mark of '0'.
*
- * Returns a new xmlChar * containing the concatenated string.
+ * Returns a new xmlChar * containing the concatenated string. The original
+ * @cur is reallocated and should not be freed.
*/
xmlChar *
xmlStrcat(xmlChar *cur, const xmlChar *add) {
* Returns the number of characters written to @buf or -1 if an error occurs.
*/
int XMLCDECL
-xmlStrPrintf(xmlChar *buf, int len, const xmlChar *msg, ...) {
+xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
va_list args;
int ret;
* Returns the number of characters written to @buf or -1 if an error occurs.
*/
int
-xmlStrVPrintf(xmlChar *buf, int len, const xmlChar *msg, va_list ap) {
+xmlStrVPrintf(xmlChar *buf, int len, const char *msg, va_list ap) {
int ret;
if((buf == NULL) || (msg == NULL)) {
* @len: the number of characters in the array
*
* storage size of an UTF8 string
- * the behaviour is not garanteed if the input string is not UTF-8
+ * the behaviour is not guaranteed if the input string is not UTF-8
*
* Returns the storage size of
* the first 'len' characters of ARRAY
break;
if ( (ch = *ptr++) & 0x80)
while ((ch<<=1) & 0x80 ) {
- ptr++;
if (*ptr == 0) break;
+ ptr++;
}
}
return (ptr - utf);
return(xmlUTF8Strndup(utf, len));
}
+/**
+ * xmlEscapeFormatString:
+ * @msg: a pointer to the string in which to escape '%' characters.
+ * Must be a heap-allocated buffer created by libxml2 that may be
+ * returned, or that may be freed and replaced.
+ *
+ * Replaces the string pointed to by 'msg' with an escaped string.
+ * Returns the same string with all '%' characters escaped.
+ */
+xmlChar *
+xmlEscapeFormatString(xmlChar **msg)
+{
+ xmlChar *msgPtr = NULL;
+ xmlChar *result = NULL;
+ xmlChar *resultPtr = NULL;
+ size_t count = 0;
+ size_t msgLen = 0;
+ size_t resultLen = 0;
+
+ if (!msg || !*msg)
+ return(NULL);
+
+ for (msgPtr = *msg; *msgPtr != '\0'; ++msgPtr) {
+ ++msgLen;
+ if (*msgPtr == '%')
+ ++count;
+ }
+
+ if (count == 0)
+ return(*msg);
+
+ resultLen = msgLen + count + 1;
+ result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
+ if (result == NULL) {
+ /* Clear *msg to prevent format string vulnerabilities in
+ out-of-memory situations. */
+ xmlFree(*msg);
+ *msg = NULL;
+ xmlErrMemory(NULL, NULL);
+ return(NULL);
+ }
+
+ for (msgPtr = *msg, resultPtr = result; *msgPtr != '\0'; ++msgPtr, ++resultPtr) {
+ *resultPtr = *msgPtr;
+ if (*msgPtr == '%')
+ *(++resultPtr) = '%';
+ }
+ result[resultLen - 1] = '\0';
+
+ xmlFree(*msg);
+ *msg = result;
+
+ return *msg;
+}
+
#define bottom_xmlstring
#include "elfgcchack.h"
XMLPUBFUN int XMLCALL
xmlStrPrintf (xmlChar *buf,
int len,
- const xmlChar *msg,
- ...);
+ const char *msg,
+ ...) LIBXML_ATTR_FORMAT(3,4);
XMLPUBFUN int XMLCALL
xmlStrVPrintf (xmlChar *buf,
int len,
- const xmlChar *msg,
- va_list ap);
+ const char *msg,
+ va_list ap) LIBXML_ATTR_FORMAT(3,0);
XMLPUBFUN int XMLCALL
xmlGetUTF8Char (const unsigned char *utf,
} xmlUnicodeRange;
typedef struct {
- xmlUnicodeRange *table;
+ const xmlUnicodeRange *table;
int numentries;
} xmlUnicodeNameTable;
static xmlIntFunc *xmlUnicodeLookup(xmlUnicodeNameTable *tptr, const char *tname);
-static xmlUnicodeRange xmlUnicodeBlocks[] = {
+static const xmlUnicodeRange xmlUnicodeBlocks[] = {
{"AegeanNumbers", xmlUCSIsAegeanNumbers},
{"AlphabeticPresentationForms", xmlUCSIsAlphabeticPresentationForms},
{"Arabic", xmlUCSIsArabic},
static xmlIntFunc
*xmlUnicodeLookup(xmlUnicodeNameTable *tptr, const char *tname) {
int low, high, mid, cmp;
- xmlUnicodeRange *sptr;
+ const xmlUnicodeRange *sptr;
if ((tptr == NULL) || (tname == NULL)) return(NULL);
*
* the version string like "1.2.3"
*/
-#define LIBXML_DOTTED_VERSION "2.9.3"
+#define LIBXML_DOTTED_VERSION "2.9.9"
/**
* LIBXML_VERSION:
*
* the version number: 1.2.3 value is 10203
*/
-#define LIBXML_VERSION 20903
+#define LIBXML_VERSION 20909
/**
* LIBXML_VERSION_STRING:
*
* the version number string, 1.2.3 value is "10203"
*/
-#define LIBXML_VERSION_STRING "20903"
+#define LIBXML_VERSION_STRING "20909"
/**
* LIBXML_VERSION_EXTRA:
*
* extra version information, used to show a CVS compilation
*/
-#define LIBXML_VERSION_EXTRA "-GITCVE-2015-8242"
+#define LIBXML_VERSION_EXTRA "-GITv2.9.9-rc2-2-g7c4949afa"
/**
* LIBXML_TEST_VERSION:
* Macro to check that the libxml version in use is compatible with
* the version the software has been compiled against
*/
-#define LIBXML_TEST_VERSION xmlCheckVersion(20903);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20909);
#ifndef VMS
#if 0
#endif
#ifdef __GNUC__
-#ifdef HAVE_ANSIDECL_H
-#include <ansidecl.h>
-#endif
/**
* ATTRIBUTE_UNUSED:
static int xmlCmpTextWriterNsStackEntry(const void *data0,
const void *data1);
static int xmlTextWriterWriteDocCallback(void *context,
- const xmlChar * str, int len);
+ const char *str, int len);
static int xmlTextWriterCloseDocCallback(void *context);
-static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr);
+static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr) LIBXML_ATTR_FORMAT(1,0);
static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len,
const unsigned char *data);
static void xmlTextWriterStartDocumentCallback(void *ctx);
*
* Handle a writer error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error,
const char *msg, int val)
{
}
memset(ret, 0, (size_t) sizeof(xmlTextWriter));
- ret->nodes = xmlListCreate((xmlListDeallocator)
- xmlFreeTextWriterStackEntry,
- (xmlListDataCompare)
+ ret->nodes = xmlListCreate(xmlFreeTextWriterStackEntry,
xmlCmpTextWriterStackEntry);
if (ret->nodes == NULL) {
xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
return NULL;
}
- ret->nsstack = xmlListCreate((xmlListDeallocator)
- xmlFreeTextWriterNsStackEntry,
- (xmlListDataCompare)
+ ret->nsstack = xmlListCreate(xmlFreeTextWriterNsStackEntry,
xmlCmpTextWriterNsStackEntry);
if (ret->nsstack == NULL) {
xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY,
return NULL;
}
- out = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
- xmlTextWriterWriteDocCallback,
- (xmlOutputCloseCallback)
+ out = xmlOutputBufferCreateIO(xmlTextWriterWriteDocCallback,
xmlTextWriterCloseDocCallback,
(void *) ctxt, NULL);
if (out == NULL) {
if (count < 0)
return -1;
sum += count;
+ /* Falls through. */
case XML_TEXTWRITER_DTD_ENTY:
case XML_TEXTWRITER_DTD_PENT:
count = xmlOutputBufferWriteString(writer->out, ">");
* Returns -1, 0, 1
*/
static int
-xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len)
+xmlTextWriterWriteDocCallback(void *context, const char *str, int len)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context;
int rc;
- if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) {
+ if ((rc = xmlParseChunk(ctxt, str, len, 0)) != 0) {
xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
"xmlTextWriterWriteDocCallback : XML error %d !\n",
rc);
if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) {
xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR,
- "xmlTextWriterWriteDocCallback : XML error %d !\n",
+ "xmlTextWriterCloseDocCallback : XML error %d !\n",
rc);
return -1;
}
* xpath.c: XML Path Language implementation
* XPath is a language for addressing parts of an XML document,
* designed to be used by both XSLT and XPointer
- *f
+ *
* Reference: W3C Recommendation 16 November 1999
* http://www.w3.org/TR/1999/REC-xpath-19991116
* Public reference:
*
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
+#include <limits.h>
#include <string.h>
+#include <stddef.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
int misc = 0, precedence1 = 0, precedence2 = 0;
xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
xmlNodePtr cur, root;
- long l1, l2;
+ ptrdiff_t l1, l2;
if ((node1 == NULL) || (node2 == NULL))
return(-2);
switch (node1->type) {
case XML_ELEMENT_NODE:
if (node2->type == XML_ELEMENT_NODE) {
- if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
- (0 > (long) node2->content) &&
+ if ((0 > (ptrdiff_t) node1->content) &&
+ (0 > (ptrdiff_t) node2->content) &&
(node1->doc == node2->doc))
{
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
+ l1 = -((ptrdiff_t) node1->content);
+ l2 = -((ptrdiff_t) node2->content);
if (l1 < l2)
return(1);
if (l1 > l2)
node1 = node1->parent;
}
if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
- (0 <= (long) node1->content)) {
+ (0 <= (ptrdiff_t) node1->content)) {
/*
* Fallback for whatever case.
*/
node2 = node2->parent;
}
if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
- (0 <= (long) node2->content))
+ (0 <= (ptrdiff_t) node2->content))
{
node2 = miscNode2;
precedence2 = 0;
*/
if ((node1->type == XML_ELEMENT_NODE) &&
(node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
+ (0 > (ptrdiff_t) node1->content) &&
+ (0 > (ptrdiff_t) node2->content) &&
(node1->doc == node2->doc)) {
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
+ l1 = -((ptrdiff_t) node1->content);
+ l2 = -((ptrdiff_t) node2->content);
if (l1 < l2)
return(1);
if (l1 > l2)
*/
if ((node1->type == XML_ELEMENT_NODE) &&
(node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
+ (0 > (ptrdiff_t) node1->content) &&
+ (0 > (ptrdiff_t) node2->content) &&
(node1->doc == node2->doc)) {
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
+ l1 = -((ptrdiff_t) node1->content);
+ l2 = -((ptrdiff_t) node2->content);
if (l1 < l2)
return(1);
if (l1 > l2)
* *
************************************************************************/
-#ifndef TRIO_REPLACE_STDIO
-#define TRIO_PUBLIC static
+#ifndef INFINITY
+#define INFINITY (DBL_MAX * DBL_MAX)
#endif
-#include "trionan.c"
-/*
- * The lack of portability of this section of the libc is annoying !
- */
-double xmlXPathNAN = 0;
-double xmlXPathPINF = 1;
-double xmlXPathNINF = -1;
-static double xmlXPathNZERO = 0; /* not exported from headers */
-static int xmlXPathInitialized = 0;
+#ifndef NAN
+#define NAN (INFINITY / INFINITY)
+#endif
+
+double xmlXPathNAN;
+double xmlXPathPINF;
+double xmlXPathNINF;
/**
* xmlXPathInit:
*/
void
xmlXPathInit(void) {
- if (xmlXPathInitialized) return;
-
- xmlXPathPINF = trio_pinf();
- xmlXPathNINF = trio_ninf();
- xmlXPathNAN = trio_nan();
- xmlXPathNZERO = trio_nzero();
-
- xmlXPathInitialized = 1;
+ xmlXPathNAN = NAN;
+ xmlXPathPINF = INFINITY;
+ xmlXPathNINF = -INFINITY;
}
/**
* xmlXPathIsNaN:
* @val: a double value
*
- * Provides a portable isnan() function to detect whether a double
- * is a NotaNumber. Based on trio code
- * http://sourceforge.net/projects/ctrio/
- *
* Returns 1 if the value is a NaN, 0 otherwise
*/
int
xmlXPathIsNaN(double val) {
- return(trio_isnan(val));
+#ifdef isnan
+ return isnan(val);
+#else
+ return !(val == val);
+#endif
}
/**
* xmlXPathIsInf:
* @val: a double value
*
- * Provides a portable isinf() function to detect whether a double
- * is a +Infinite or -Infinite. Based on trio code
- * http://sourceforge.net/projects/ctrio/
- *
- * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
+ * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
*/
int
xmlXPathIsInf(double val) {
- return(trio_isinf(val));
+#ifdef isinf
+ return isinf(val) ? (val > 0 ? 1 : -1) : 0;
+#else
+ if (val >= INFINITY)
+ return 1;
+ if (val <= -INFINITY)
+ return -1;
+ return 0;
+#endif
}
#endif /* SCHEMAS or XPATH */
-#ifdef LIBXML_XPATH_ENABLED
-/**
- * xmlXPathGetSign:
- * @val: a double value
- *
- * Provides a portable function to detect the sign of a double
- * Modified from trio code
- * http://sourceforge.net/projects/ctrio/
- *
- * Returns 1 if the value is Negative, 0 if positive
- */
-static int
-xmlXPathGetSign(double val) {
- return(trio_signbit(val));
-}
+#ifdef LIBXML_XPATH_ENABLED
/*
* TODO: when compatibility allows remove all "fake node libxslt" strings
xmlChar buf[200];
xmlStrPrintf(buf, 200,
- BAD_CAST "Memory allocation failed : %s\n",
+ "Memory allocation failed : %s\n",
extra);
ctxt->lastError.message = (char *) xmlStrdup(buf);
} else {
XPATH_OP_UNION,
XPATH_OP_ROOT,
XPATH_OP_NODE,
- XPATH_OP_RESET, /* 10 */
XPATH_OP_COLLECT,
- XPATH_OP_VALUE, /* 12 */
+ XPATH_OP_VALUE, /* 11 */
XPATH_OP_VARIABLE,
XPATH_OP_FUNCTION,
XPATH_OP_ARG,
XPATH_OP_PREDICATE,
- XPATH_OP_FILTER, /* 17 */
- XPATH_OP_SORT /* 18 */
+ XPATH_OP_FILTER, /* 16 */
+ XPATH_OP_SORT /* 17 */
#ifdef LIBXML_XPTR_ENABLED
,XPATH_OP_RANGETO
#endif
int value3;
void *value4;
void *value5;
- void *cache;
+ xmlXPathFunction cache;
void *cacheURI;
};
xmlXPathStepOp *steps; /* ops for computation of this expression */
int last; /* index of last step in expression */
xmlChar *expr; /* the expression being computed */
- xmlDictPtr dict; /* the dictionnary to use if any */
+ xmlDictPtr dict; /* the dictionary to use if any */
#ifdef DEBUG_EVAL_COUNTS
int nb;
xmlChar *string;
xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
xmlXPathStepOpPtr op,
int isPredicate);
+static void
+xmlXPathFreeObjectEntry(void *obj, const xmlChar *name);
/************************************************************************
* *
default:
if (xmlXPathIsNaN(cur->floatval)) {
fprintf(output, "Object is a number : NaN\n");
- } else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
+ } else if (cur->floatval == 0) {
+ /* Omit sign for negative zero. */
fprintf(output, "Object is a number : 0\n");
} else {
fprintf(output, "Object is a number : %0g\n", cur->floatval);
fprintf(output, "ROOT"); break;
case XPATH_OP_NODE:
fprintf(output, "NODE"); break;
- case XPATH_OP_RESET:
- fprintf(output, "RESET"); break;
case XPATH_OP_SORT:
fprintf(output, "SORT"); break;
case XPATH_OP_COLLECT: {
fprintf(output, "%s", shift);
- fprintf(output, "Compiled Expression : %d elements\n",
- comp->nbStep);
- i = comp->last;
- xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
+#ifdef XPATH_STREAMING
+ if (comp->stream) {
+ fprintf(output, "Streaming Expression\n");
+ } else
+#endif
+ {
+ fprintf(output, "Compiled Expression : %d elements\n",
+ comp->nbStep);
+ i = comp->last;
+ xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
+ }
}
#ifdef XP_DEBUG_OBJ_USAGE
if (xmlXPathIsNaN(number)) {
if (buffersize > (int)sizeof("NaN"))
snprintf(buffer, buffersize, "NaN");
- } else if (number == 0 && xmlXPathGetSign(number) != 0) {
+ } else if (number == 0) {
+ /* Omit sign for negative zero. */
snprintf(buffer, buffersize, "0");
- } else if (number == ((int) number)) {
+ } else if ((number > INT_MIN) && (number < INT_MAX) &&
+ (number == (int) number)) {
char work[30];
char *ptr, *cur;
int value = (int) number;
*/
long
xmlXPathOrderDocElems(xmlDocPtr doc) {
- long count = 0;
+ ptrdiff_t count = 0;
xmlNodePtr cur;
if (doc == NULL)
}
} while (cur != NULL);
}
- return(count);
+ return((long) count);
}
/**
*/
if ((node1->type == XML_ELEMENT_NODE) &&
(node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
+ (0 > (ptrdiff_t) node1->content) &&
+ (0 > (ptrdiff_t) node2->content) &&
(node1->doc == node2->doc)) {
- long l1, l2;
+ ptrdiff_t l1, l2;
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
+ l1 = -((ptrdiff_t) node1->content);
+ l2 = -((ptrdiff_t) node2->content);
if (l1 < l2)
return(1);
if (l1 > l2)
* compute depth to root
*/
for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
- if (cur == node1)
+ if (cur->parent == node1)
return(1);
depth2++;
}
root = cur;
for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
- if (cur == node2)
+ if (cur->parent == node2)
return(-1);
depth1++;
}
*/
if ((node1->type == XML_ELEMENT_NODE) &&
(node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
+ (0 > (ptrdiff_t) node1->content) &&
+ (0 > (ptrdiff_t) node2->content) &&
(node1->doc == node2->doc)) {
- long l1, l2;
+ ptrdiff_t l1, l2;
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
+ l1 = -((ptrdiff_t) node1->content);
+ l2 = -((ptrdiff_t) node2->content);
if (l1 < l2)
return(1);
if (l1 > l2)
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
/*
- * prevent duplcates
+ * prevent duplicates
*/
for (i = 0;i < cur->nodeNr;i++)
if (cur->nodeTab[i] == val) return(0);
set1->nodeTab = temp;
set1->nodeMax *= 2;
}
- if (n2->type == XML_NAMESPACE_DECL) {
- xmlNsPtr ns = (xmlNsPtr) n2;
-
- set1->nodeTab[set1->nodeNr++] =
- xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
- } else
- set1->nodeTab[set1->nodeNr++] = n2;
+ set1->nodeTab[set1->nodeNr++] = n2;
skip_node:
{}
}
xmlFree(obj);
}
-/**
- * xmlXPathNodeSetClear:
- * @set: the node set to clear
- *
- * Clears the list from all temporary XPath objects (e.g. namespace nodes
- * are feed), but does *not* free the list itself. Sets the length of the
- * list to 0.
- */
-static void
-xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
-{
- if ((set == NULL) || (set->nodeNr <= 0))
- return;
- else if (hasNsNodes) {
- int i;
- xmlNodePtr node;
-
- for (i = 0; i < set->nodeNr; i++) {
- node = set->nodeTab[i];
- if ((node != NULL) &&
- (node->type == XML_NAMESPACE_DECL))
- xmlXPathNodeSetFreeNs((xmlNsPtr) node);
- }
- }
- set->nodeNr = 0;
-}
-
/**
* xmlXPathNodeSetClearFromPos:
* @set: the node set to be cleared
static void
xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes)
{
- if ((set == NULL) || (set->nodeNr <= 0) || (pos >= set->nodeNr))
+ if ((set == NULL) || (pos >= set->nodeNr))
return;
else if ((hasNsNodes)) {
int i;
set->nodeNr = pos;
}
+/**
+ * xmlXPathNodeSetClear:
+ * @set: the node set to clear
+ *
+ * Clears the list from all temporary XPath objects (e.g. namespace nodes
+ * are feed), but does *not* free the list itself. Sets the length of the
+ * list to 0.
+ */
+static void
+xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
+{
+ xmlXPathNodeSetClearFromPos(set, 0, hasNsNodes);
+}
+
+/**
+ * xmlXPathNodeSetKeepLast:
+ * @set: the node set to be cleared
+ *
+ * Move the last node to the first position and clear temporary XPath objects
+ * (e.g. namespace nodes) from all other nodes. Sets the length of the list
+ * to 1.
+ */
+static void
+xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)
+{
+ int i;
+ xmlNodePtr node;
+
+ if ((set == NULL) || (set->nodeNr <= 1))
+ return;
+ for (i = 0; i < set->nodeNr - 1; i++) {
+ node = set->nodeTab[i];
+ if ((node != NULL) &&
+ (node->type == XML_NAMESPACE_DECL))
+ xmlXPathNodeSetFreeNs((xmlNsPtr) node);
+ }
+ set->nodeTab[0] = set->nodeTab[set->nodeNr-1];
+ set->nodeNr = 1;
+}
+
/**
* xmlXPathFreeValueTree:
* @obj: the xmlNodeSetPtr to free
xmlFree(strval);
}
}
- xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
+ xmlHashFree(hash, xmlHashDefaultDeallocator);
return(ret);
}
return(-1);
if (f == NULL)
return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
- return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, XML_CAST_FPTR(f)));
+XML_IGNORE_PEDANTIC_WARNINGS
+ return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f));
+XML_POP_WARNINGS
}
/**
if (ctxt->funcHash == NULL)
return(NULL);
- XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
+XML_IGNORE_PEDANTIC_WARNINGS
+ ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
+XML_POP_WARNINGS
return(ret);
}
return(-1);
if (value == NULL)
return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
- (xmlHashDeallocator)xmlXPathFreeObject));
+ xmlXPathFreeObjectEntry));
return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
- (void *) value,
- (xmlHashDeallocator)xmlXPathFreeObject));
+ (void *) value, xmlXPathFreeObjectEntry));
}
/**
if (ctxt == NULL)
return;
- xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
+ xmlHashFree(ctxt->varHash, xmlXPathFreeObjectEntry);
ctxt->varHash = NULL;
}
return(-1);
if (ns_uri == NULL)
return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
- (xmlHashDeallocator)xmlFree));
+ xmlHashDefaultDeallocator));
return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
- (xmlHashDeallocator)xmlFree));
+ xmlHashDefaultDeallocator));
}
/**
if (ctxt == NULL)
return;
- xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree);
+ xmlHashFree(ctxt->nsHash, xmlHashDefaultDeallocator);
ctxt->nsHash = NULL;
}
xmlFree(obj);
}
+static void
+xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlXPathFreeObject((xmlXPathObjectPtr) obj);
+}
+
/**
* xmlXPathReleaseObject:
* @obj: the xmlXPathObjectPtr to free or to cache
default:
if (xmlXPathIsNaN(val)) {
ret = xmlStrdup((const xmlChar *) "NaN");
- } else if (val == 0 && xmlXPathGetSign(val) != 0) {
+ } else if (val == 0) {
+ /* Omit sign for negative zero. */
ret = xmlStrdup((const xmlChar *) "0");
} else {
/* could be improved */
double ret;
if (node == NULL)
- return(xmlXPathNAN);
+ return(NAN);
strval = xmlXPathCastNodeToString(node);
if (strval == NULL)
- return(xmlXPathNAN);
+ return(NAN);
ret = xmlXPathCastStringToNumber(strval);
xmlFree(strval);
double ret;
if (ns == NULL)
- return(xmlXPathNAN);
+ return(NAN);
str = xmlXPathCastNodeSetToString(ns);
ret = xmlXPathCastStringToNumber(str);
xmlFree(str);
double ret = 0.0;
if (val == NULL)
- return(xmlXPathNAN);
+ return(NAN);
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEGUB_EXPR
xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
#endif
- ret = xmlXPathNAN;
+ ret = NAN;
break;
case XPATH_NODESET:
case XPATH_XSLT_TREE:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO;
- ret = xmlXPathNAN;
+ ret = NAN;
break;
}
return(ret);
*/
void
xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
+ int i;
+
if (ctxt->valueTab != NULL) {
+ for (i = 0; i < ctxt->valueNr; i++) {
+ if (ctxt->context)
+ xmlXPathReleaseObject(ctxt->context, ctxt->valueTab[i]);
+ else
+ xmlXPathFreeObject(ctxt->valueTab[i]);
+ }
xmlFree(ctxt->valueTab);
}
if (ctxt->comp != NULL) {
}
while (tmp != NULL) {
switch (tmp->type) {
- case XML_COMMENT_NODE:
- case XML_PI_NODE:
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
string = tmp->content;
break;
- case XML_NAMESPACE_DECL:
- string = ((xmlNsPtr)tmp)->href;
- break;
default:
+ string = NULL;
break;
}
if ((string != NULL) && (string[0] != 0)) {
valuePush(ctxt, val);
return(xmlXPathCompareValues(ctxt, inf, strict));
default:
- TODO
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompareNodeSetValue: Can't compare node set "
+ "and object of type %d\n",
+ val->type);
+ xmlXPathReleaseObject(ctxt->context, arg);
+ xmlXPathReleaseObject(ctxt->context, val);
+ XP_ERROR0(XPATH_INVALID_TYPE);
}
return(0);
}
valuePush(ctxt, arg2);
xmlXPathNumberFunction(ctxt, 1);
arg2 = valuePop(ctxt);
- /* no break on purpose */
+ /* Falls through. */
case XPATH_NUMBER:
/* Hand check NaN and Infinity equalities */
if (xmlXPathIsNaN(arg1->floatval) ||
if ((ctxt == NULL) || (ctxt->context == NULL)) return;
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
- if (xmlXPathIsNaN(ctxt->value->floatval))
- ctxt->value->floatval=xmlXPathNAN;
- else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
- ctxt->value->floatval=xmlXPathNINF;
- else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
- ctxt->value->floatval=xmlXPathPINF;
- else if (ctxt->value->floatval == 0) {
- if (xmlXPathGetSign(ctxt->value->floatval) == 0)
- ctxt->value->floatval = xmlXPathNZERO;
- else
- ctxt->value->floatval = 0;
- }
- else
- ctxt->value->floatval = - ctxt->value->floatval;
+ ctxt->value->floatval = -ctxt->value->floatval;
}
/**
xmlXPathReleaseObject(ctxt->context, arg);
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
- if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
- ctxt->value->floatval = xmlXPathNAN;
- else if (val == 0 && xmlXPathGetSign(val) != 0) {
- if (ctxt->value->floatval == 0)
- ctxt->value->floatval = xmlXPathNAN;
- else if (ctxt->value->floatval > 0)
- ctxt->value->floatval = xmlXPathNINF;
- else if (ctxt->value->floatval < 0)
- ctxt->value->floatval = xmlXPathPINF;
- }
- else if (val == 0) {
- if (ctxt->value->floatval == 0)
- ctxt->value->floatval = xmlXPathNAN;
- else if (ctxt->value->floatval > 0)
- ctxt->value->floatval = xmlXPathPINF;
- else if (ctxt->value->floatval < 0)
- ctxt->value->floatval = xmlXPathNINF;
- } else
- ctxt->value->floatval /= val;
+ ctxt->value->floatval /= val;
}
/**
CHECK_TYPE(XPATH_NUMBER);
arg1 = ctxt->value->floatval;
if (arg2 == 0)
- ctxt->value->floatval = xmlXPathNAN;
+ ctxt->value->floatval = NAN;
else {
ctxt->value->floatval = fmod(arg1, arg2);
}
return(NULL);
return(cur->parent);
case XML_ATTRIBUTE_NODE: {
- xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
+ xmlAttrPtr att = (xmlAttrPtr) cur;
return(att->parent);
}
case XML_NAMESPACE_DECL: {
- xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
+ xmlNsPtr ns = (xmlNsPtr) cur;
if ((ns->next != NULL) &&
(ns->next->type != XML_NAMESPACE_DECL))
if (cur == NULL) {
cur = ctxt->context->node;
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
- if (cur->type == XML_ATTRIBUTE_NODE)
+ if (cur->type == XML_ATTRIBUTE_NODE) {
cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
}
if (cur == NULL) return(NULL) ; /* ERROR */
if (cur->next != NULL) return(cur->next) ;
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if (cur == NULL) {
cur = ctxt->context->node;
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
- if (cur->type == XML_ATTRIBUTE_NODE)
- return(cur->parent);
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+ cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
}
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
return (NULL);
cur = ctxt->context->node;
if (cur == NULL)
return (NULL);
- if (cur->type == XML_NAMESPACE_DECL)
- return (NULL);
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+ cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
ctxt->ancestor = cur->parent;
}
if (cur->type == XML_NAMESPACE_DECL)
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
- if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
+ if (cur == NULL) {
if (ctxt->context->tmpNsList != NULL)
xmlFree(ctxt->context->tmpNsList);
ctxt->context->tmpNsList =
xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
if ((ctxt == NULL) || (ctxt->context == NULL))
return;
- ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
- ctxt->context->node));
+ (xmlNodePtr) ctxt->context->doc));
}
/************************************************************************
xmlXPathReleaseObject(ctxt->context, cur);
}
-/*
- * To assure working code on multiple platforms, we want to only depend
- * upon the characteristic truncation of converting a floating point value
- * to an integer. Unfortunately, because of the different storage sizes
- * of our internal floating point value (double) and integer (int), we
- * can't directly convert (see bug 301162). This macro is a messy
- * 'workaround'
- */
-#define XTRUNC(f, v) \
- f = fmod((v), INT_MAX); \
- f = (v) - (f) + (double)((int)(f));
-
/**
* xmlXPathFloorFunction:
* @ctxt: the XPath Parser context
*/
void
xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- double f;
-
CHECK_ARITY(1);
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
- XTRUNC(f, ctxt->value->floatval);
- if (f != ctxt->value->floatval) {
- if (ctxt->value->floatval > 0)
- ctxt->value->floatval = f;
- else
- ctxt->value->floatval = f - 1;
- }
+ ctxt->value->floatval = floor(ctxt->value->floatval);
}
/**
*/
void
xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- double f;
-
CHECK_ARITY(1);
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
-#if 0
ctxt->value->floatval = ceil(ctxt->value->floatval);
-#else
- XTRUNC(f, ctxt->value->floatval);
- if (f != ctxt->value->floatval) {
- if (ctxt->value->floatval > 0)
- ctxt->value->floatval = f + 1;
- else {
- if (ctxt->value->floatval < 0 && f == 0)
- ctxt->value->floatval = xmlXPathNZERO;
- else
- ctxt->value->floatval = f;
- }
-
- }
-#endif
}
/**
* number round(number)
* The round function returns the number that is closest to the
* argument and that is an integer. If there are two such numbers,
- * then the one that is even is returned.
+ * then the one that is closest to positive infinity is returned.
*/
void
xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
- if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
- (xmlXPathIsInf(ctxt->value->floatval) == 1) ||
- (xmlXPathIsInf(ctxt->value->floatval) == -1) ||
- (ctxt->value->floatval == 0.0))
- return;
+ f = ctxt->value->floatval;
- XTRUNC(f, ctxt->value->floatval);
- if (ctxt->value->floatval < 0) {
- if (ctxt->value->floatval < f - 0.5)
- ctxt->value->floatval = f - 1;
- else
- ctxt->value->floatval = f;
- if (ctxt->value->floatval == 0)
- ctxt->value->floatval = xmlXPathNZERO;
- } else {
- if (ctxt->value->floatval < f + 0.5)
- ctxt->value->floatval = f;
- else
- ctxt->value->floatval = f + 1;
+ if ((f >= -0.5) && (f < 0.5)) {
+ /* Handles negative zero. */
+ ctxt->value->floatval *= 0.0;
+ }
+ else {
+ double rounded = floor(f);
+ if (f - rounded >= 0.5)
+ rounded += 1.0;
+ ctxt->value->floatval = rounded;
}
}
(c == '[') || (c == ']') || (c == '@') || /* accelerators */
(c == '*') || /* accelerators */
(!IS_LETTER(c) && (c != '_') &&
- ((qualified) && (c != ':')))) {
+ ((!qualified) || (c != ':')))) {
return(NULL);
}
#define MAX_FRAC 20
-/*
- * These are used as divisors for the fractional part of a number.
- * Since the table includes 1.0 (representing '0' fractional digits),
- * it must be dimensioned at MAX_FRAC+1 (bug 133921)
- */
-static double my_pow10[MAX_FRAC+1] = {
- 1.0, 10.0, 100.0, 1000.0, 10000.0,
- 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
- 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
- 100000000000000.0,
- 1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
- 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0
-};
-
/**
* xmlXPathStringEvalNumber:
* @str: A string to scan
if (cur == NULL) return(0);
while (IS_BLANK_CH(*cur)) cur++;
if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
- return(xmlXPathNAN);
+ return(NAN);
}
if (*cur == '-') {
isneg = 1;
#endif
if (*cur == '.') {
- int v, frac = 0;
+ int v, frac = 0, max;
double fraction = 0;
cur++;
if (((*cur < '0') || (*cur > '9')) && (!ok)) {
- return(xmlXPathNAN);
+ return(NAN);
}
- while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
+ while (*cur == '0') {
+ frac = frac + 1;
+ cur++;
+ }
+ max = frac + MAX_FRAC;
+ while (((*cur >= '0') && (*cur <= '9')) && (frac < max)) {
v = (*cur - '0');
fraction = fraction * 10 + v;
frac = frac + 1;
cur++;
}
- fraction /= my_pow10[frac];
+ fraction /= pow(10.0, frac);
ret = ret + fraction;
while ((*cur >= '0') && (*cur <= '9'))
cur++;
cur++;
}
while ((*cur >= '0') && (*cur <= '9')) {
- exponent = exponent * 10 + (*cur - '0');
+ if (exponent < 1000000)
+ exponent = exponent * 10 + (*cur - '0');
cur++;
}
}
while (IS_BLANK_CH(*cur)) cur++;
- if (*cur != 0) return(xmlXPathNAN);
+ if (*cur != 0) return(NAN);
if (isneg) ret = -ret;
if (is_exponent_negative) exponent = -exponent;
ret *= pow(10.0, (double)exponent);
}
#endif
if (CUR == '.') {
- int v, frac = 0;
+ int v, frac = 0, max;
double fraction = 0;
NEXT;
if (((CUR < '0') || (CUR > '9')) && (!ok)) {
XP_ERROR(XPATH_NUMBER_ERROR);
}
- while ((CUR >= '0') && (CUR <= '9') && (frac < MAX_FRAC)) {
+ while (CUR == '0') {
+ frac = frac + 1;
+ NEXT;
+ }
+ max = frac + MAX_FRAC;
+ while ((CUR >= '0') && (CUR <= '9') && (frac < max)) {
v = (CUR - '0');
fraction = fraction * 10 + v;
frac = frac + 1;
NEXT;
}
- fraction /= my_pow10[frac];
+ fraction /= pow(10.0, frac);
ret = ret + fraction;
while ((CUR >= '0') && (CUR <= '9'))
NEXT;
NEXT;
}
while ((CUR >= '0') && (CUR <= '9')) {
- exponent = exponent * 10 + (CUR - '0');
+ if (exponent < 1000000)
+ exponent = exponent * 10 + (CUR - '0');
NEXT;
}
if (is_exponent_negative)
NEXT;
name = xmlXPathParseQName(ctxt, &prefix);
if (name == NULL) {
+ xmlFree(prefix);
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
}
ctxt->comp->last = -1;
#endif
if (CUR != '(') {
+ xmlFree(name);
+ xmlFree(prefix);
XP_ERROR(XPATH_EXPR_ERROR);
}
NEXT;
nbargs++;
if (CUR == ')') break;
if (CUR != ',') {
+ xmlFree(name);
+ xmlFree(prefix);
XP_ERROR(XPATH_EXPR_ERROR);
}
NEXT;
lc = 1;
break;
} else if ((NXT(len) == '(')) {
- /* Note Type or Function */
+ /* Node Type or Function */
if (xmlXPathIsNodeType(name)) {
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext,
"PathExpr: Type search\n");
#endif
lc = 1;
+#ifdef LIBXML_XPTR_ENABLED
+ } else if (ctxt->xptr &&
+ xmlStrEqual(name, BAD_CAST "range-to")) {
+ lc = 1;
+#endif
} else {
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext,
PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
- PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
xmlXPathCompRelativeLocationPath(ctxt);
} else if (CUR == '/') {
xmlXPathContextPtr xpctxt = ctxt->context;
xmlNodePtr contextNode, oldContextNode;
xmlDocPtr oldContextDoc;
+ int oldcs, oldpp;
int i, res, contextPos = 0, newContextSize;
xmlXPathStepOpPtr exprOp;
xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
*/
oldContextNode = xpctxt->node;
oldContextDoc = xpctxt->doc;
+ oldcs = xpctxt->contextSize;
+ oldpp = xpctxt->proximityPosition;
/*
* Get the expression of this predicate.
*/
*/
xpctxt->node = oldContextNode;
xpctxt->doc = oldContextDoc;
- xpctxt->contextSize = -1;
- xpctxt->proximityPosition = -1;
+ xpctxt->contextSize = oldcs;
+ xpctxt->proximityPosition = oldpp;
return(newContextSize);
}
return(contextSize);
return (contextSize);
} else {
xmlDocPtr oldContextDoc;
+ int oldcs, oldpp;
int i, pos = 0, newContextSize = 0, contextPos = 0, res;
xmlXPathStepOpPtr exprOp;
xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
*/
oldContextNode = xpctxt->node;
oldContextDoc = xpctxt->doc;
+ oldcs = xpctxt->contextSize;
+ oldpp = xpctxt->proximityPosition;
/*
* Get the expression of this predicate.
*/
}
}
- frame = xmlXPathSetFrame(ctxt);
valuePush(ctxt, contextObj);
+ frame = xmlXPathSetFrame(ctxt);
res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
- tmp = valuePop(ctxt);
xmlXPathPopFrame(ctxt, frame);
+ tmp = valuePop(ctxt);
if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
while (tmp != contextObj) {
*/
xpctxt->node = oldContextNode;
xpctxt->doc = oldContextDoc;
- xpctxt->contextSize = -1;
- xpctxt->proximityPosition = -1;
+ xpctxt->contextSize = oldcs;
+ xpctxt->proximityPosition = oldpp;
return(newContextSize);
}
return(contextSize);
(exprOp->value4 != NULL) &&
(((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
{
+ double floatval = ((xmlXPathObjectPtr) exprOp->value4)->floatval;
+
/*
* We have a "[n]" predicate here.
* TODO: Unfortunately this simplistic test here is not
* like it "[position() < 5]", is also not detected.
* Maybe we could rewrite the AST to ease the optimization.
*/
- *maxPos = (int) ((xmlXPathObjectPtr) exprOp->value4)->floatval;
- if (((xmlXPathObjectPtr) exprOp->value4)->floatval ==
- (float) *maxPos)
- {
- return(1);
- }
+ if ((floatval > INT_MIN) && (floatval < INT_MAX)) {
+ *maxPos = (int) floatval;
+ if (floatval == (double) *maxPos)
+ return(1);
+ }
}
return(0);
}
STRANGE
goto error;
case NODE_TEST_TYPE:
- /*
- * TODO: Don't we need to use
- * xmlXPathNodeSetAddNs() for namespace nodes here?
- * Surprisingly, some c14n tests fail, if we do this.
- */
if (type == NODE_TYPE_NODE) {
switch (cur->type) {
case XML_DOCUMENT_NODE:
case XML_COMMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
- case XML_NAMESPACE_DECL:
XP_TEST_HIT
break;
+ case XML_NAMESPACE_DECL: {
+ if (axis == AXIS_NAMESPACE) {
+ XP_TEST_HIT_NS
+ } else {
+ hasNsNodes = 1;
+ XP_TEST_HIT
+ }
+ break;
+ }
default:
break;
}
- } else if (cur->type == type) {
+ } else if (cur->type == (xmlElementType) type) {
if (cur->type == XML_NAMESPACE_DECL)
XP_TEST_HIT_NS
else
* Reset the context node.
*/
xpctxt->node = oldContextNode;
+ /*
+ * When traversing the namespace axis in "toBool" mode, it's
+ * possible that tmpNsList wasn't freed.
+ */
+ if (xpctxt->tmpNsList != NULL) {
+ xmlFree(xpctxt->tmpNsList);
+ xpctxt->tmpNsList = NULL;
+ }
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext,
xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
first);
CHECK_ERROR0;
- CHECK_TYPE0(XPATH_NODESET);
- arg2 = valuePop(ctxt);
- CHECK_TYPE0(XPATH_NODESET);
+ arg2 = valuePop(ctxt);
arg1 = valuePop(ctxt);
+ if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
+ (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
+ xmlXPathReleaseObject(ctxt->context, arg1);
+ xmlXPathReleaseObject(ctxt->context, arg2);
+ XP_ERROR0(XPATH_INVALID_TYPE);
+ }
arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
arg2->nodesetval);
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (total);
int total = 0, cur;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- xmlNodePtr bak;
- xmlDocPtr bakd;
- int pp;
- int cs;
CHECK_ERROR0;
comp = ctxt->comp;
case XPATH_OP_END:
return (0);
case XPATH_OP_UNION:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total =
xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
CHECK_ERROR0;
nodesetval->nodeNr -
1];
}
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
cur =
xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
CHECK_ERROR0;
&& (ctxt->value->nodesetval != NULL)
&& (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */
}
- CHECK_TYPE0(XPATH_NODESET);
- arg2 = valuePop(ctxt);
- CHECK_TYPE0(XPATH_NODESET);
+ arg2 = valuePop(ctxt);
arg1 = valuePop(ctxt);
+ if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
+ (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
+ xmlXPathReleaseObject(ctxt->context, arg1);
+ xmlXPathReleaseObject(ctxt->context, arg2);
+ XP_ERROR0(XPATH_INVALID_TYPE);
+ }
arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
arg2->nodesetval);
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (0);
xmlNodeSetPtr oldset;
xmlNodePtr oldnode;
xmlDocPtr oldDoc;
+ int oldcs, oldpp;
int i;
CHECK_ERROR0;
(ctxt->value->nodesetval != NULL) &&
(ctxt->value->nodesetval->nodeTab != NULL) &&
(ctxt->value->nodesetval->nodeNr > 1)) {
- ctxt->value->nodesetval->nodeTab[0] =
- ctxt->value->nodesetval->nodeTab[ctxt->
- value->
- nodesetval->
- nodeNr -
- 1];
- ctxt->value->nodesetval->nodeNr = 1;
+ xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
*first = *(ctxt->value->nodesetval->nodeTab);
}
return (total);
return (total);
#ifdef LIBXML_XPTR_ENABLED
- oldnode = ctxt->context->node;
/*
* Hum are we filtering the result of an XPointer expression
*/
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- ctxt->context->node = NULL;
+ oldnode = ctxt->context->node;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
if (op->ch2 != -1)
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto xptr_error;
}
/*
* The result of the evaluation need to be tested to
/* OLD: xmlXPathFreeObject(res); */
} else
tmp = NULL;
- ctxt->context->node = NULL;
/*
* Only put the first node in the result, then leave.
*/
/*
* The result is used as the new evaluation locset.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+xptr_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
ctxt->context->node = oldnode;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
* up a new set.
*/
CHECK_TYPE0(XPATH_NODESET);
- obj = valuePop(ctxt);
- oldset = obj->nodesetval;
- oldnode = ctxt->context->node;
- oldDoc = ctxt->context->doc;
- ctxt->context->node = NULL;
-
- if ((oldset == NULL) || (oldset->nodeNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- /* QUESTION TODO: Why was this code commented out?
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- CHECK_ERROR0;
- res = valuePop(ctxt);
- if (res != NULL)
- xmlXPathFreeObject(res);
- */
- valuePush(ctxt, obj);
- ctxt->context->node = oldnode;
- CHECK_ERROR0;
- } else {
+ if ((ctxt->value->nodesetval != NULL) &&
+ (ctxt->value->nodesetval->nodeNr != 0)) {
xmlNodeSetPtr newset;
xmlXPathObjectPtr tmp = NULL;
+
+ obj = valuePop(ctxt);
+ oldset = obj->nodesetval;
+ oldnode = ctxt->context->node;
+ oldDoc = ctxt->context->doc;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
+
/*
* Initialize the new set.
* Also set the xpath document in case things like
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
- xmlXPathFreeObject(obj);
- return(0);
+ goto error;
}
/*
* The result of the evaluation needs to be tested to
xmlXPathNodeSetClear(tmp->nodesetval, 1);
} else
tmp = NULL;
- ctxt->context->node = NULL;
/*
* Only put the first node in the result, then leave.
*/
/*
* The result is used as the new evaluation set.
*/
+ valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+error:
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
- /* may want to move this past the '}' later */
+ ctxt->context->node = oldnode;
ctxt->context->doc = oldDoc;
- valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
}
- ctxt->context->node = oldnode;
return(total);
}
#endif /* XP_OPTIMIZED_FILTER_FIRST */
int equal, ret;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- xmlNodePtr bak;
- xmlDocPtr bakd;
- int pp;
- int cs;
CHECK_ERROR0;
comp = ctxt->comp;
case XPATH_OP_END:
return (0);
case XPATH_OP_AND:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
xmlXPathBooleanFunction(ctxt, 1);
if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error) {
xmlXPathFreeObject(arg2);
return(0);
}
xmlXPathBooleanFunction(ctxt, 1);
- arg1 = valuePop(ctxt);
- arg1->boolval &= arg2->boolval;
- valuePush(ctxt, arg1);
+ if (ctxt->value != NULL)
+ ctxt->value->boolval &= arg2->boolval;
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_OR:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
xmlXPathBooleanFunction(ctxt, 1);
if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error) {
xmlXPathFreeObject(arg2);
return(0);
}
xmlXPathBooleanFunction(ctxt, 1);
- arg1 = valuePop(ctxt);
- arg1->boolval |= arg2->boolval;
- valuePush(ctxt, arg1);
+ if (ctxt->value != NULL)
+ ctxt->value->boolval |= arg2->boolval;
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_EQUAL:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
if (op->value)
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
return (total);
case XPATH_OP_CMP:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
return (total);
case XPATH_OP_PLUS:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
if (op->ch2 != -1) {
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
}
CHECK_ERROR0;
}
return (total);
case XPATH_OP_MULT:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
if (op->value == 0)
xmlXPathModValues(ctxt);
return (total);
case XPATH_OP_UNION:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
- CHECK_TYPE0(XPATH_NODESET);
- arg2 = valuePop(ctxt);
- CHECK_TYPE0(XPATH_NODESET);
+ arg2 = valuePop(ctxt);
arg1 = valuePop(ctxt);
+ if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
+ (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
+ xmlXPathReleaseObject(ctxt->context, arg1);
+ xmlXPathReleaseObject(ctxt->context, arg2);
+ XP_ERROR0(XPATH_INVALID_TYPE);
+ }
if ((arg1->nodesetval == NULL) ||
((arg2->nodesetval != NULL) &&
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (total);
xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
if (op->value5 == NULL) {
val = xmlXPathVariableLookup(ctxt->context, op->value4);
- if (val == NULL) {
- ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
- return(0);
- }
+ if (val == NULL)
+ XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
valuePush(ctxt, val);
} else {
const xmlChar *URI;
}
val = xmlXPathVariableLookupNS(ctxt->context,
op->value4, URI);
- if (val == NULL) {
- ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
- return(0);
- }
+ if (val == NULL)
+ XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
valuePush(ctxt, val);
}
return (total);
}
}
if (op->cache != NULL)
- XML_CAST_FPTR(func) = op->cache;
+ func = op->cache;
else {
const xmlChar *URI = NULL;
(char *)op->value4);
XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
}
- op->cache = XML_CAST_FPTR(func);
+ op->cache = func;
op->cacheURI = (void *) URI;
}
oldFunc = ctxt->context->function;
return (total);
}
case XPATH_OP_ARG:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
if (op->ch1 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- ctxt->context->contextSize = cs;
- ctxt->context->proximityPosition = pp;
- ctxt->context->node = bak;
- ctxt->context->doc = bakd;
CHECK_ERROR0;
}
if (op->ch2 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- ctxt->context->contextSize = cs;
- ctxt->context->proximityPosition = pp;
- ctxt->context->node = bak;
- ctxt->context->doc = bakd;
CHECK_ERROR0;
}
return (total);
xmlNodeSetPtr oldset;
xmlNodePtr oldnode;
xmlDocPtr oldDoc;
+ int oldcs, oldpp;
int i;
/*
(ctxt->value->type == XPATH_NODESET) &&
(ctxt->value->nodesetval != NULL) &&
(ctxt->value->nodesetval->nodeNr > 1))
- ctxt->value->nodesetval->nodeNr = 1;
+ xmlXPathNodeSetClearFromPos(ctxt->value->nodesetval,
+ 1, 1);
return (total);
}
}
(ctxt->value->type == XPATH_NODESET) &&
(ctxt->value->nodesetval != NULL) &&
(ctxt->value->nodesetval->nodeTab != NULL) &&
- (ctxt->value->nodesetval->nodeNr > 1)) {
- ctxt->value->nodesetval->nodeTab[0] =
- ctxt->value->nodesetval->nodeTab[ctxt->
- value->
- nodesetval->
- nodeNr -
- 1];
- ctxt->value->nodesetval->nodeNr = 1;
- }
+ (ctxt->value->nodesetval->nodeNr > 1))
+ xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
return (total);
}
}
if (ctxt->value == NULL)
return (total);
- oldnode = ctxt->context->node;
-
#ifdef LIBXML_XPTR_ENABLED
/*
* Hum are we filtering the result of an XPointer expression
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- ctxt->context->node = NULL;
+ oldnode = ctxt->context->node;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto filter_xptr_error;
}
/*
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
/*
* The result is used as the new evaluation locset.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+filter_xptr_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
ctxt->context->node = oldnode;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
* up a new set.
*/
CHECK_TYPE0(XPATH_NODESET);
- obj = valuePop(ctxt);
- oldset = obj->nodesetval;
-
- oldnode = ctxt->context->node;
- oldDoc = ctxt->context->doc;
- ctxt->context->node = NULL;
- if ((oldset == NULL) || (oldset->nodeNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
-/*
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- CHECK_ERROR0;
- res = valuePop(ctxt);
- if (res != NULL)
- xmlXPathFreeObject(res);
-*/
- valuePush(ctxt, obj);
- ctxt->context->node = oldnode;
- CHECK_ERROR0;
- } else {
+ if ((ctxt->value->nodesetval != NULL) &&
+ (ctxt->value->nodesetval->nodeNr != 0)) {
+ obj = valuePop(ctxt);
+ oldset = obj->nodesetval;
+ oldnode = ctxt->context->node;
+ oldDoc = ctxt->context->doc;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
tmp = NULL;
/*
* Initialize the new set.
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
- xmlXPathFreeObject(obj);
- return(0);
+ goto filter_error;
}
/*
*/
} else
tmp = NULL;
- ctxt->context->node = NULL;
}
if (tmp != NULL)
xmlXPathReleaseObject(ctxt->context, tmp);
/*
* The result is used as the new evaluation set.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
- /* may want to move this past the '}' later */
- ctxt->context->doc = oldDoc;
valuePush(ctxt,
xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+filter_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
+ ctxt->context->node = oldnode;
+ ctxt->context->doc = oldDoc;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
}
- ctxt->context->node = oldnode;
return (total);
}
case XPATH_OP_SORT:
xmlLocationSetPtr newlocset = NULL;
xmlLocationSetPtr oldlocset;
xmlNodeSetPtr oldset;
+ xmlNodePtr oldnode = ctxt->context->node;
+ int oldcs = ctxt->context->contextSize;
+ int oldpp = ctxt->context->proximityPosition;
int i, j;
- if (op->ch1 != -1)
+ if (op->ch1 != -1) {
total +=
xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
+ CHECK_ERROR0;
+ }
+ if (ctxt->value == NULL) {
+ XP_ERROR0(XPATH_INVALID_OPERAND);
+ }
if (op->ch2 == -1)
return (total);
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->node = NULL;
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto rangeto_error;
}
res = valuePop(ctxt);
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
} else { /* Not a location set */
CHECK_TYPE0(XPATH_NODESET);
obj = valuePop(ctxt);
oldset = obj->nodesetval;
- ctxt->context->node = NULL;
newlocset = xmlXPtrLocationSetCreate(NULL);
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto rangeto_error;
}
res = valuePop(ctxt);
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
}
}
/*
* The result is used as the new evaluation set.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+rangeto_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
+ ctxt->context->node = oldnode;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
}
}
+ /* OP_VALUE has invalid ch1. */
+ if (op->op == XPATH_OP_VALUE)
+ return;
+
/* Recurse */
if (op->ch1 != -1)
xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
static int
xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
xmlXPathContextPtr ctxt,
- xmlXPathObjectPtr *resObj,
+ xmlXPathObjectPtr *resObjPtr,
int toBool)
{
xmlXPathParserContextPtr pctxt;
+ xmlXPathObjectPtr resObj;
#ifndef LIBXML_THREAD_ENABLED
static int reentance = 0;
#endif
pctxt = xmlXPathCompParserContext(comp, ctxt);
res = xmlXPathRunEval(pctxt, toBool);
- if (resObj) {
- if (pctxt->value == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlXPathCompiledEval: evaluation failed\n");
- *resObj = NULL;
- } else {
- *resObj = valuePop(pctxt);
- }
+ if (pctxt->error != XPATH_EXPRESSION_OK) {
+ resObj = NULL;
+ } else {
+ resObj = valuePop(pctxt);
+ if (resObj == NULL) {
+ if (!toBool)
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompiledEval: No result on the stack.\n");
+ } else if (pctxt->valueNr > 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompiledEval: %d object(s) left on the stack.\n",
+ pctxt->valueNr);
+ }
}
- /*
- * Pop all remaining objects from the stack.
- */
- if (pctxt->valueNr > 0) {
- xmlXPathObjectPtr tmp;
- int stack = 0;
-
- do {
- tmp = valuePop(pctxt);
- if (tmp != NULL) {
- stack++;
- xmlXPathReleaseObject(ctxt, tmp);
- }
- } while (tmp != NULL);
- if ((stack != 0) &&
- ((toBool) || ((resObj) && (*resObj))))
- {
- xmlGenericError(xmlGenericErrorContext,
- "xmlXPathCompiledEval: %d objects left on the stack.\n",
- stack);
- }
- }
+ if (resObjPtr)
+ *resObjPtr = resObj;
+ else
+ xmlXPathReleaseObject(ctxt, resObj);
- if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) {
- xmlXPathFreeObject(*resObj);
- *resObj = NULL;
- }
pctxt->comp = NULL;
xmlXPathFreeParserContext(pctxt);
#ifndef LIBXML_THREAD_ENABLED
if (ctxt->comp != NULL)
xmlXPathFreeCompExpr(ctxt->comp);
ctxt->comp = comp;
- if (ctxt->cur != NULL)
- while (*ctxt->cur != 0) ctxt->cur++;
} else
#endif
{
xmlXPathCompileExpr(ctxt, 1);
- if ((ctxt->error == XPATH_EXPRESSION_OK) &&
- (ctxt->comp != NULL) &&
- (ctxt->comp->nbStep > 1) &&
- (ctxt->comp->last >= 0))
- {
+ CHECK_ERROR;
+
+ /* Check for trailing characters. */
+ if (*ctxt->cur != 0)
+ XP_ERROR(XPATH_EXPR_ERROR);
+
+ if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0))
xmlXPathOptimizeExpression(ctxt->comp,
&ctxt->comp->steps[ctxt->comp->last]);
- }
}
- CHECK_ERROR;
+
xmlXPathRunEval(ctxt, 0);
}
xmlXPathObjectPtr
xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
xmlXPathParserContextPtr ctxt;
- xmlXPathObjectPtr res, tmp, init = NULL;
- int stack = 0;
+ xmlXPathObjectPtr res;
CHECK_CTXT(ctx)
return NULL;
xmlXPathEvalExpr(ctxt);
- if (ctxt->value == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlXPathEval: evaluation failed\n");
- res = NULL;
- } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL)
-#ifdef XPATH_STREAMING
- && (ctxt->comp->stream == NULL)
-#endif
- ) {
- xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
+ if (ctxt->error != XPATH_EXPRESSION_OK) {
res = NULL;
} else {
res = valuePop(ctxt);
- }
-
- do {
- tmp = valuePop(ctxt);
- if (tmp != NULL) {
- if (tmp != init)
- stack++;
- xmlXPathReleaseObject(ctx, tmp);
+ if (res == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompiledEval: No result on the stack.\n");
+ } else if (ctxt->valueNr > 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompiledEval: %d object(s) left on the stack.\n",
+ ctxt->valueNr);
}
- } while (tmp != NULL);
- if ((stack != 0) && (res != NULL)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlXPathEval: %d object left on the stack\n",
- stack);
- }
- if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(res);
- res = NULL;
}
xmlXPathFreeParserContext(ctxt);
* @str: the XPath expression
* @ctxt: the XPath context
*
- * Evaluate the XPath expression in the given context.
+ * Alias for xmlXPathEval().
*
* Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
* the caller has to free the object.
*/
xmlXPathObjectPtr
xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
- xmlXPathParserContextPtr pctxt;
- xmlXPathObjectPtr res, tmp;
- int stack = 0;
-
- CHECK_CTXT(ctxt)
-
- xmlXPathInit();
-
- pctxt = xmlXPathNewParserContext(str, ctxt);
- if (pctxt == NULL)
- return NULL;
- xmlXPathEvalExpr(pctxt);
-
- if ((*pctxt->cur != 0) || (pctxt->error != XPATH_EXPRESSION_OK)) {
- xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
- res = NULL;
- } else {
- res = valuePop(pctxt);
- }
- do {
- tmp = valuePop(pctxt);
- if (tmp != NULL) {
- xmlXPathReleaseObject(ctxt, tmp);
- stack++;
- }
- } while (tmp != NULL);
- if ((stack != 0) && (res != NULL)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlXPathEvalExpression: %d object left on the stack\n",
- stack);
- }
- xmlXPathFreeParserContext(pctxt);
- return(res);
+ return(xmlXPathEval(str, ctxt));
}
/************************************************************************
* Empties a node-set.
*/
#define xmlXPathEmptyNodeSet(ns) \
- { while ((ns)->nodeNr > 0) (ns)->nodeTab[(ns)->nodeNr--] = NULL; }
+ { while ((ns)->nodeNr > 0) (ns)->nodeTab[--(ns)->nodeNr] = NULL; }
/**
* CHECK_ERROR:
* daniel@veillard.com
*/
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
#define IN_LIBXML
#include "libxml.h"
*
* Handle a redefinition of attribute error
*/
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
const char * msg, const xmlChar *extra)
{
msg, extra);
return;
}
+
+ /* cleanup current last error */
+ xmlResetError(&ctxt->context->lastError);
+
ctxt->context->lastError.domain = XML_FROM_XPOINTER;
ctxt->context->lastError.code = error;
ctxt->context->lastError.level = XML_ERR_ERROR;
return(1);
}
+/**
+ * xmlXPtrNewRangeInternal:
+ * @start: the starting node
+ * @startindex: the start index
+ * @end: the ending point
+ * @endindex: the ending index
+ *
+ * Internal function to create a new xmlXPathObjectPtr of type range
+ *
+ * Returns the newly created object.
+ */
+static xmlXPathObjectPtr
+xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
+ xmlNodePtr end, int endindex) {
+ xmlXPathObjectPtr ret;
+
+ /*
+ * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
+ * Disallow them for now.
+ */
+ if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
+ return(NULL);
+ if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
+ return(NULL);
+
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+ if (ret == NULL) {
+ xmlXPtrErrMemory("allocating range");
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(xmlXPathObject));
+ ret->type = XPATH_RANGE;
+ ret->user = start;
+ ret->index = startindex;
+ ret->user2 = end;
+ ret->index2 = endindex;
+ return(ret);
+}
+
/**
* xmlXPtrNewRange:
* @start: the starting node
if (endindex < 0)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = startindex;
- ret->user2 = end;
- ret->index2 = endindex;
+ ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
if (end->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start->user;
- ret->index = start->index;
- ret->user2 = end->user;
- ret->index2 = end->index;
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
+ end->index);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
if (start->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start->user;
- ret->index = start->index;
- ret->user2 = end;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
return(NULL);
if (end == NULL)
return(NULL);
- if (start->type != XPATH_POINT)
- return(NULL);
if (end->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = end->user;
- ret->index2 = end->index;
+ ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
if (end == NULL)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = end;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
if (start == NULL)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = NULL;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
return(ret);
}
*/
xmlXPathObjectPtr
xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+ xmlNodePtr endNode;
+ int endIndex;
xmlXPathObjectPtr ret;
if (start == NULL)
return(NULL);
switch (end->type) {
case XPATH_POINT:
+ endNode = end->user;
+ endIndex = end->index;
+ break;
case XPATH_RANGE:
+ endNode = end->user2;
+ endIndex = end->index2;
break;
case XPATH_NODESET:
/*
* Empty set ...
*/
- if (end->nodesetval->nodeNr <= 0)
+ if ((end->nodesetval == NULL) || (end->nodesetval->nodeNr <= 0))
return(NULL);
+ endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
+ endIndex = -1;
break;
default:
/* TODO */
return(NULL);
}
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- switch (end->type) {
- case XPATH_POINT:
- ret->user2 = end->user;
- ret->index2 = end->index;
- break;
- case XPATH_RANGE:
- ret->user2 = end->user2;
- ret->index2 = end->index2;
- break;
- case XPATH_NODESET: {
- ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
- ret->index2 = -1;
- break;
- }
- default:
- STRANGE
- return(NULL);
- }
+ ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
if (name == NULL)
XP_ERROR(XPATH_EXPR_ERROR);
- if (CUR != '(')
+ if (CUR != '(') {
+ xmlFree(name);
XP_ERROR(XPATH_EXPR_ERROR);
+ }
NEXT;
level = 1;
buffer = (xmlChar *) xmlMallocAtomic(len * sizeof (xmlChar));
if (buffer == NULL) {
xmlXPtrErrMemory("allocating buffer");
+ xmlFree(name);
return;
}
*cur = 0;
if ((level != 0) && (CUR == 0)) {
+ xmlFree(name);
xmlFree(buffer);
XP_ERROR(XPTR_SYNTAX_ERROR);
}
if (name2 == NULL) {
CUR_PTR = left;
xmlFree(buffer);
+ xmlFree(name);
XP_ERROR(XPATH_EXPR_ERROR);
}
xmlXPtrEvalChildSeq(ctxt, name2);
ret->here = here;
ret->origin = origin;
- xmlXPathRegisterFunc(ret, (xmlChar *)"range-to",
- xmlXPtrRangeToFunction);
xmlXPathRegisterFunc(ret, (xmlChar *)"range",
xmlXPtrRangeFunction);
xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
*/
xmlNodeSetPtr set;
set = tmp->nodesetval;
- if ((set->nodeNr != 1) ||
+ if ((set == NULL) || (set->nodeNr != 1) ||
(set->nodeTab[0] != (xmlNodePtr) ctx->doc))
stack++;
} else
case XPATH_RANGE: {
xmlNodePtr node = tmp->user;
if (node != NULL) {
- if (node->type == XML_ATTRIBUTE_NODE) {
- /* TODO: Namespace Nodes ??? */
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
+ (node->type == XML_NAMESPACE_DECL)) {
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);
case XPATH_RANGE: {
xmlNodePtr node = tmp->user2;
if (node != NULL) {
- if (node->type == XML_ATTRIBUTE_NODE) {
- /* TODO: Namespace Nodes ??? */
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
+ (node->type == XML_NAMESPACE_DECL)) {
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);
xmlXPathFreeObject(set);
XP_ERROR(XPATH_MEMORY_ERROR);
}
- for (i = 0;i < oldset->locNr;i++) {
- xmlXPtrLocationSetAdd(newset,
- xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
+ if (oldset != NULL) {
+ for (i = 0;i < oldset->locNr;i++) {
+ xmlXPtrLocationSetAdd(newset,
+ xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
+ }
}
/*
* @nargs: the number of args
*
* Implement the range-to() XPointer function
+ *
+ * Obsolete. range-to is not a real function but a special type of location
+ * step which is handled in xpath.c.
*/
void
-xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- xmlXPathObjectPtr range;
- const xmlChar *cur;
- xmlXPathObjectPtr res, obj;
- xmlXPathObjectPtr tmp;
- xmlLocationSetPtr newset = NULL;
- xmlNodeSetPtr oldset;
- int i;
-
- if (ctxt == NULL) return;
- CHECK_ARITY(1);
- /*
- * Save the expression pointer since we will have to evaluate
- * it multiple times. Initialize the new set.
- */
- CHECK_TYPE(XPATH_NODESET);
- obj = valuePop(ctxt);
- oldset = obj->nodesetval;
- ctxt->context->node = NULL;
-
- cur = ctxt->cur;
- newset = xmlXPtrLocationSetCreate(NULL);
-
- for (i = 0; i < oldset->nodeNr; i++) {
- ctxt->cur = cur;
-
- /*
- * Run the evaluation with a node list made of a single item
- * in the nodeset.
- */
- ctxt->context->node = oldset->nodeTab[i];
- tmp = xmlXPathNewNodeSet(ctxt->context->node);
- valuePush(ctxt, tmp);
-
- xmlXPathEvalExpr(ctxt);
- CHECK_ERROR;
-
- /*
- * The result of the evaluation need to be tested to
- * decided whether the filter succeeded or not
- */
- res = valuePop(ctxt);
- range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res);
- if (range != NULL) {
- xmlXPtrLocationSetAdd(newset, range);
- }
-
- /*
- * Cleanup
- */
- if (res != NULL)
- xmlXPathFreeObject(res);
- if (ctxt->value == tmp) {
- res = valuePop(ctxt);
- xmlXPathFreeObject(res);
- }
-
- ctxt->context->node = NULL;
- }
-
- /*
- * The result is used as the new evaluation set.
- */
- xmlXPathFreeObject(obj);
- ctxt->context->node = NULL;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
- valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
+xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
+ int nargs ATTRIBUTE_UNUSED) {
+ XP_ERROR(XPATH_EXPR_ERROR);
}
/**
-# libxml.m4 serial 7
+# libxml.m4 serial 8
dnl Copyright (C) 2006, 2008, 2011, 2013, 2016, 2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
# include <arpa/nameser.h>
#endif
])
- AC_CHECK_FUNCS([dlopen getaddrinfo localtime shlload stat _stat strftime])
+ AC_CHECK_FUNCS([dlopen getaddrinfo localtime shlload stat strftime])
dnl This relies on the va_copy replacement from the stdarg module.
AC_DEFINE([VA_COPY], [va_copy],
[Define to a working va_copy macro or replacement.])