more work on the XML catalog support. small cleanup seems using list as a

* Makefile.am catalog.c xmlcatalog.c include/libxml/catalog.h:
  more work on the XML catalog support.
* parser.c include/libxml/parser.h: small cleanup seems using
  list as a public parameter name can give portability troubles
* trionan.c trionan.h xpath.c include/libxml/trionan.h
  include/libxml/xpath.h include/libxml/Makefile.am: removed
  trionan from the libxml API, added xmlXPathIsInf and xmlXPathIsNaN
  wrappers
Daniel
diff --git a/ChangeLog b/ChangeLog
index 4d8e21f..851b849 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Tue Aug 21 12:52:38 CEST 2001 Daniel Veillard <daniel@veillard.com>
+
+	* Makefile.am catalog.c xmlcatalog.c include/libxml/catalog.h:
+	  more work on the XML catalog support.
+	* parser.c include/libxml/parser.h: small cleanup seems using
+	  list as a public parameter name can give portability troubles
+	* trionan.c trionan.h xpath.c include/libxml/trionan.h
+	  include/libxml/xpath.h include/libxml/Makefile.am: removed
+	  trionan from the libxml API, added xmlXPathIsInf and xmlXPathIsNaN
+	  wrappers
+
 Tue Aug 21 11:18:45 CEST 2001 Bjorn Reese <breese@users.sourceforge.net>
 
 	* Makefile.am trio.c triodef.h trionan.c xpath.c
diff --git a/Makefile.am b/Makefile.am
index 36f24b1..5a3f70d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,14 +23,14 @@
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
 		valid.c xlink.c HTMLparser.c HTMLtree.c debugXML.c xpath.c  \
 		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
-		catalog.c trionan.c strio.c trio.c
+		catalog.c strio.c trio.c
 
 else
 libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c  \
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
 		valid.c xlink.c HTMLparser.c HTMLtree.c debugXML.c xpath.c  \
 		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
-		catalog.c trionan.c
+		catalog.c 
 
 endif
 
@@ -81,7 +81,7 @@
 
 testall : tests SVGtests SAXtests
 
-tests: XMLtests XMLenttests HTMLtests Validtests URItests XPathtests XPtrtests XIncludetests Scripttests
+tests: XMLtests XMLenttests HTMLtests Validtests URItests XPathtests XPtrtests XIncludetests Scripttests Catatests
 
 HTMLtests : testHTML
 	@(echo > .memdump)
@@ -378,6 +378,26 @@
 	      rm result.$$name ; \
 	  fi ; fi ; done)
 
+Catatests : xmlcatalog
+	@(echo > .memdump)
+	@echo "##"
+	@echo "## Catalog regression tests"
+	@echo "##"
+	@(for i in $(srcdir)/test/catalogs/*.script ; do \
+	  name=`basename $$i .script`; \
+	  xml=$(srcdir)/test/catalogs/`basename $$i .script`.xml; \
+	  if [ -f $$xml ] ; then \
+	  if [ ! -f $(srcdir)/result/catalogs/$$name ] ; then \
+	      echo New test file $$name ; \
+	      $(top_builddir)/xmlcatalog --shell $$xml < $$i > $(srcdir)/result/catalogs/$$name ; \
+	  else \
+	      echo Testing $$name ; \
+	      $(top_builddir)/xmlcatalog --shell $$xml < $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
+	      diff $(srcdir)/result/catalogs/$$name result.$$name ; \
+	      rm result.$$name ; \
+	  fi ; fi ; done)
+
 SVGtests : xmllint
 	@echo "##"
 	@echo "## SVG parsing regression tests"
diff --git a/catalog.c b/catalog.c
index a5e0631..d645d88 100644
--- a/catalog.c
+++ b/catalog.c
@@ -45,6 +45,7 @@
 	    "Unimplemented block at %s:%d\n",				\
             __FILE__, __LINE__);
 
+#define XML_URN_PUBID "urn:publicid:"
 
 /************************************************************************
  *									*
@@ -92,6 +93,7 @@
     xmlCatalogEntryType type;
     xmlChar *name;
     xmlChar *value;
+    /* TODO : 1234 xmlCatalogPrefer prefer */
 };
 
 static xmlHashTablePtr xmlDefaultCatalog;
@@ -251,6 +253,9 @@
 static void
 xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
 	                   xmlCatalogEntryPtr parent);
+static xmlChar *
+xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
+	              const xmlChar *sysID);
 
 static xmlCatalogEntryType
 xmlGetXMLCatalogEntryType(const xmlChar *name) {
@@ -540,6 +545,49 @@
     return(parent);
 }
 
+/**
+ * xmlFetchXMLCatalogFile:
+ * @catal:  an existing but incomplete catalog entry
+ *
+ * Fetch and parse the subcatalog referenced by an entry
+ * It tries to be thread safe but by lack of an atomic test and
+ * set there is a risk of loosing memory.
+ * 
+ * Returns 0 in case of success, -1 otherwise
+ */
+static int
+xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
+    xmlCatalogEntryPtr children;
+
+    if (catal == NULL) 
+	return(-1);
+    if (catal->value == NULL)
+	return(-1);
+    if (catal->children != NULL)
+	return(-1);
+
+    /*
+     * Fetch and parse
+     */
+    /* TODO : 1234 s/XML_CATA_PREFER_PUBLIC/catal->prefer */
+    children = xmlParseXMLCatalogFile(XML_CATA_PREFER_PUBLIC, catal->value);
+    if (children == NULL)
+	return(-1);
+
+    /*
+     * Where a real test and set would be needed !
+     */
+    if (catal->children == NULL) {
+	catal->children = children;
+    } else {
+	/*
+	 * Another thread filled it before us
+	 */
+	xmlFreeCatalogEntryList(children);
+    }
+    return(0);
+}
+
 static int
 xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
     int ret;
@@ -682,7 +730,7 @@
  * xmlAddXMLCatalog:
  * @catal:  top of an XML catalog
  * @type:  the type of record to add to the catalog
- * @orig:  the system, public or prefix to match 
+ * @orig:  the system, public or prefix to match (or NULL)
  * @replace:  the replacement value for the match
  *
  * Add an entry in the XML catalog, it may overwrite existing but
@@ -708,12 +756,12 @@
      */
     if (cur != NULL) {
 	while (cur != NULL) {
-	    cur = cur->next;
-	    if ((cur->type == typ) && (xmlStrEqual(orig, cur->name))) {
+	    if ((orig != NULL) && (cur->type == typ) &&
+		(xmlStrEqual(orig, cur->name))) {
 		if (cur->value != NULL)
 		    xmlFree(cur->value);
 		cur->value = xmlStrdup(replace);
-		return(1);
+		return(0);
 	    }
 	    if (cur->next == NULL)
 		break;
@@ -724,7 +772,306 @@
 	catal->children = xmlNewCatalogEntry(typ, orig, replace);
     else
 	cur->next = xmlNewCatalogEntry(typ, orig, replace);
-    return(1);
+    return(0);
+}
+
+/**
+ * xmlDelXMLCatalog:
+ * @catal:  top of an XML catalog
+ * @value:  the value to remove from teh catalog
+ *
+ * Remove entries in the XML catalog where the value or the URI
+ * is equal to @value
+ *
+ * Returns the number of entries removed if successful, -1 otherwise
+ */
+static int
+xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
+    xmlCatalogEntryPtr cur, prev, tmp;
+    int ret = 0;
+
+    if ((catal == NULL) || (catal->type != XML_CATA_CATALOG))
+	return(-1);
+    if (value == NULL)
+	return(-1);
+
+    /*
+     * Scan the children
+     */
+    cur = catal->children;
+    prev = NULL;
+    while (cur != NULL) {
+	if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
+	    (xmlStrEqual(value, cur->value))) {
+	    ret++;
+	    tmp = cur;
+	    cur = tmp->next;
+	    if (prev == NULL) {
+		catal->children = cur;
+	    } else {
+		prev->next = cur;
+	    }
+            xmlFreeCatalogEntry(tmp);
+	    continue;
+	}
+	prev = cur;
+	cur = cur->next;
+    }
+    return(ret);
+}
+
+/**
+ * xmlCatalogGetXMLPublic:
+ * @catal:  an XML catalog
+ * @pubId:  the public ID string
+ *
+ * Try to lookup the system ID associated to a public ID
+ *
+ * Returns the system ID if found or NULL otherwise.
+ */
+static const xmlChar *
+xmlCatalogGetXMLPublic(xmlCatalogEntryPtr catal, const xmlChar *pubID) {
+    const xmlChar *ret;
+    while (catal != NULL) {
+	switch (catal->type) {
+            case XML_CATA_CATALOG:
+		if (catal->children == NULL) {
+		    if (xmlFetchXMLCatalogFile(catal))
+			break;
+		}
+		ret = xmlCatalogGetXMLPublic(catal->children, pubID);
+		if (ret != NULL)
+		    return(ret);
+		break;
+            case XML_CATA_NEXT_CATALOG:
+		if (catal->children == NULL) {
+		    if (xmlFetchXMLCatalogFile(catal))
+			break;
+		}
+            case XML_CATA_PUBLIC:
+		if (xmlStrEqual(pubID, catal->name))
+		    return(catal->value);
+		break;
+            case XML_CATA_SYSTEM:
+            case XML_CATA_REWRITE_SYSTEM:
+            case XML_CATA_DELEGATE_PUBLIC:
+            case XML_CATA_DELEGATE_SYSTEM:
+            case XML_CATA_URI:
+            case XML_CATA_REWRITE_URI:
+            case XML_CATA_DELEGATE_URI:
+		TODO;
+		break;
+
+            case XML_CATA_NONE:
+            case SGML_CATA_SYSTEM:
+            case SGML_CATA_PUBLIC:
+            case SGML_CATA_ENTITY:
+            case SGML_CATA_PENTITY:
+            case SGML_CATA_DOCTYPE:
+            case SGML_CATA_LINKTYPE:
+            case SGML_CATA_NOTATION:
+            case SGML_CATA_DELEGATE:
+            case SGML_CATA_BASE:
+            case SGML_CATA_CATALOG:
+            case SGML_CATA_DOCUMENT:
+            case SGML_CATA_SGMLDECL:
+		/* Ignored entries */
+		break;
+	}
+	catal = catal->next;
+    }
+    return(NULL);
+}
+
+/**
+ * xmlCatalogXMLResolve:
+ * @catal:  a catalog list
+ * @pubId:  the public ID string
+ * @sysId:  the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier for a
+ * list of catalog entries.
+ *
+ * Implements (or tries to) 7.1. External Identifier Resolution
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
+ *
+ * Returns the URI of the resource or NULL if not found
+ */
+static xmlChar *
+xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
+	              const xmlChar *sysID) {
+    xmlChar *ret = NULL;
+    xmlCatalogEntryPtr cur;
+    int haveDelegate = 0;
+    int haveNext = 0;
+
+    /*
+     * First tries steps 2/ 3/ 4/ if a system ID is provided.
+     */
+    if (sysID != NULL) {
+	xmlCatalogEntryPtr rewrite = NULL;
+	int lenrewrite = 0, len;
+	cur = catal;
+	haveDelegate = 0;
+	while (cur != NULL) {
+	    switch (cur->type) {
+		case XML_CATA_SYSTEM:
+		    if (xmlStrEqual(sysID, cur->name))
+			return(xmlStrdup(cur->value));
+		    break;
+		case XML_CATA_REWRITE_SYSTEM:
+		    len = xmlStrlen(cur->name);
+		    if ((len > lenrewrite) &&
+			(!xmlStrncmp(sysID, cur->name, len))) {
+			lenrewrite = len;
+			rewrite = cur;
+		    }
+		    break;
+		case XML_CATA_DELEGATE_SYSTEM:
+		    if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
+			haveDelegate++;
+		    break;
+		case XML_CATA_NEXT_CATALOG:
+		    haveNext++;
+		    break;
+		default:
+		    break;
+	    }
+	    cur = cur->next;
+	}
+	if (rewrite != NULL) {
+	    ret = xmlStrdup(rewrite->value);
+	    if (ret != NULL)
+		ret = xmlStrcat(ret, &sysID[lenrewrite]);
+	    return(ret);
+	}
+	if (haveDelegate) {
+	    /*
+	     * Assume the entries have been sorted by decreasing subscting
+	     * matches when the list was produced.
+	     */
+	    cur = catal;
+	    while (cur != NULL) {
+		if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
+		    (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
+		    if (cur->children == NULL) {
+			xmlFetchXMLCatalogFile(cur);
+		    }
+		    if (cur->children != NULL) {
+			TODO /* handle a delegate system entry */
+		    }
+		}
+		cur = cur->next;
+	    }
+	}
+    }
+    /*
+     * Then tries 5/ 6/ if a public ID is provided
+     */
+    if (pubID != NULL) {
+	cur = catal;
+	haveDelegate = 0;
+	while (cur != NULL) {
+	    switch (cur->type) {
+		case XML_CATA_PUBLIC:
+		    if (xmlStrEqual(pubID, cur->name))
+			return(xmlStrdup(cur->value));
+		    break;
+		case XML_CATA_DELEGATE_PUBLIC:
+		    if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))
+			haveDelegate++;
+		    break;
+		case XML_CATA_NEXT_CATALOG:
+		    if (sysID == NULL)
+			haveNext++;
+		    break;
+		default:
+		    break;
+	    }
+	    cur = cur->next;
+	}
+	if (haveDelegate) {
+	    /*
+	     * Assume the entries have been sorted by decreasing subscting
+	     * matches when the list was produced.
+	     */
+	    cur = catal;
+	    while (cur != NULL) {
+		if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
+		    (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
+		    if (cur->children == NULL) {
+			xmlFetchXMLCatalogFile(cur);
+		    }
+		    if (cur->children != NULL) {
+			TODO /* handle a delegate public entry */
+		    }
+		}
+		cur = cur->next;
+	    }
+	}
+    }
+    if (haveNext) {
+	cur = catal;
+	while (cur != NULL) {
+	    if (cur->type == XML_CATA_NEXT_CATALOG) {
+		if (cur->children == NULL) {
+		    xmlFetchXMLCatalogFile(cur);
+		}
+		if (cur->children != NULL) {
+		    xmlCatalogListXMLResolve(cur->children, pubID, sysID);
+		}
+	    }
+	    cur = cur->next;
+	}
+    }
+
+    return(NULL);
+}
+
+/**
+ * xmlCatalogListXMLResolve:
+ * @catal:  a catalog list
+ * @pubId:  the public ID string
+ * @sysId:  the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier for a
+ * list of catalogs
+ *
+ * Implements (or tries to) 7.1. External Identifier Resolution
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
+ *
+ * Returns the URI of the resource or NULL if not found
+ */
+static xmlChar *
+xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
+	              const xmlChar *sysID) {
+    xmlChar *ret = NULL;
+    if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID))) {
+	TODO /* convert to PublicId */
+    }
+    if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID))) {
+	TODO /* convert to PublicId and check */
+    }
+    while (catal != NULL) {
+	if (catal->type == XML_CATA_CATALOG) {
+	    if (catal->children == NULL) {
+		/*
+		 * Construct the list on the fly, then double check
+		 * in case of threaded program that it hasn't already
+		 * being built by a concurrent thread.
+		xmlCatalogEntryPtr list;
+
+		list = 
+		 */
+		TODO
+	    }
+	    ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
+	    if (ret != NULL)
+		return(ret);
+	}
+	catal = catal->next;
+    }
+    return(ret);
 }
 
 /************************************************************************
@@ -741,7 +1088,7 @@
 #define SKIP_BLANKS while (IS_BLANK(*cur)) NEXT;
 
 static const xmlChar *
-xmlParseCatalogComment(const xmlChar *cur) {
+xmlParseSGMLCatalogComment(const xmlChar *cur) {
     if ((cur[0] != '-') || (cur[1] != '-')) 
 	return(cur);
     SKIP(2);
@@ -754,7 +1101,7 @@
 }
 
 static const xmlChar *
-xmlParseCatalogPubid(const xmlChar *cur, xmlChar **id) {
+xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
     xmlChar *buf = NULL;
     int len = 0;
     int size = 50;
@@ -814,7 +1161,7 @@
 }
 
 static const xmlChar *
-xmlParseCatalogName(const xmlChar *cur, xmlChar **name) {
+xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
     xmlChar buf[XML_MAX_NAMELEN + 5];
     int len = 0;
     int c;
@@ -843,7 +1190,7 @@
 }
 
 static xmlCatalogEntryType
-xmlGetCatalogEntryType(const xmlChar *name) {
+xmlGetSGMLCatalogEntryType(const xmlChar *name) {
     xmlCatalogEntryType type = XML_CATA_NONE;
     if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
 	type = SGML_CATA_SYSTEM;
@@ -873,7 +1220,7 @@
 }
 
 static int
-xmlParseCatalog(const xmlChar *value, const char *file) {
+xmlParseSGMLCatalog(const xmlChar *value, const char *file) {
     const xmlChar *cur = value;
     xmlChar *base = NULL;
     int res;
@@ -885,7 +1232,7 @@
     while ((cur != NULL) && (cur[0] != '0')) {
 	SKIP_BLANKS;
 	if ((cur[0] == '-') && (cur[1] == '-')) {
-	    cur = xmlParseCatalogComment(cur);
+	    cur = xmlParseSGMLCatalogComment(cur);
 	    if (cur == NULL) {
 		/* error */
 		break;
@@ -895,7 +1242,7 @@
 	    xmlChar *name = NULL;
 	    xmlCatalogEntryType type = XML_CATA_NONE;
 
-	    cur = xmlParseCatalogName(cur, &name);
+	    cur = xmlParseSGMLCatalogName(cur, &name);
 	    if (name == NULL) {
 		/* error */
 		break;
@@ -931,7 +1278,7 @@
                 type = SGML_CATA_DELEGATE;
 	    else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
 		xmlFree(name);
-		cur = xmlParseCatalogName(cur, &name);
+		cur = xmlParseSGMLCatalogName(cur, &name);
 		if (name == NULL) {
 		    /* error */
 		    break;
@@ -950,7 +1297,7 @@
 		case SGML_CATA_DOCTYPE:
 		case SGML_CATA_LINKTYPE:
 		case SGML_CATA_NOTATION:
-		    cur = xmlParseCatalogName(cur, &name);
+		    cur = xmlParseSGMLCatalogName(cur, &name);
 		    if (cur == NULL) {
 			/* error */
 			break;
@@ -960,7 +1307,7 @@
 			break;
 		    }
 		    SKIP_BLANKS;
-		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    cur = xmlParseSGMLCatalogPubid(cur, &sysid);
 		    if (cur == NULL) {
 			/* error */
 			break;
@@ -969,7 +1316,7 @@
 		case SGML_CATA_PUBLIC:
 		case SGML_CATA_SYSTEM:
 		case SGML_CATA_DELEGATE:
-		    cur = xmlParseCatalogPubid(cur, &name);
+		    cur = xmlParseSGMLCatalogPubid(cur, &name);
 		    if (cur == NULL) {
 			/* error */
 			break;
@@ -979,7 +1326,7 @@
 			break;
 		    }
 		    SKIP_BLANKS;
-		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    cur = xmlParseSGMLCatalogPubid(cur, &sysid);
 		    if (cur == NULL) {
 			/* error */
 			break;
@@ -989,7 +1336,7 @@
 		case SGML_CATA_CATALOG:
 		case SGML_CATA_DOCUMENT:
 		case SGML_CATA_SGMLDECL:
-		    cur = xmlParseCatalogPubid(cur, &sysid);
+		    cur = xmlParseSGMLCatalogPubid(cur, &sysid);
 		    if (cur == NULL) {
 			/* error */
 			break;
@@ -1049,6 +1396,45 @@
     return(0);
 }
 
+/**
+ * xmlCatalogGetSGMLPublic:
+ * @catal:  an SGML catalog hash
+ * @pubId:  the public ID string
+ *
+ * Try to lookup the system ID associated to a public ID
+ *
+ * Returns the system ID if found or NULL otherwise.
+ */
+static const xmlChar *
+xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
+    xmlCatalogEntryPtr entry;
+
+    if (catal == NULL)
+	return(NULL);
+
+    entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
+    if (entry == NULL)
+	return(NULL);
+    if (entry->type == SGML_CATA_PUBLIC)
+	return(entry->value);
+    return(NULL);
+}
+
+/**
+ * xmlCatalogSGMLResolve:
+ * @pubId:  the public ID string
+ * @sysId:  the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier
+ *
+ * Returns the URI of the resource or NULL if not found
+ */
+static const xmlChar *
+xmlCatalogSGMLResolve(const xmlChar *pubID, const xmlChar *sysID) {
+    TODO
+    return(NULL);
+}
+
 /************************************************************************
  *									*
  *			Public interfaces				*
@@ -1127,7 +1513,7 @@
     if ((content[0] == ' ') || (content[0] == '-') ||
 	((content[0] >= 'A') && (content[0] <= 'Z')) ||
 	((content[0] >= 'a') && (content[0] <= 'z')))
-	ret = xmlParseCatalog(content, filename);
+	ret = xmlParseSGMLCatalog(content, filename);
     else {
 	xmlCatalogEntryPtr catal, tmp;
 	/* TODO: allow to switch the default preference */
@@ -1190,6 +1576,8 @@
  */
 void
 xmlCatalogCleanup(void) {
+    if (xmlDefaultXMLCatalogList != NULL)
+	xmlFreeCatalogEntryList(xmlDefaultXMLCatalogList);
     if (xmlDefaultCatalog != NULL)
 	xmlHashFree(xmlDefaultCatalog,
 		    (xmlHashDeallocator) xmlFreeCatalogEntry);
@@ -1219,91 +1607,6 @@
 }
 
 /**
- * xmlCatalogGetXMLPublic:
- * @catal:  an XML catalog
- * @pubId:  the public ID string
- *
- * Try to lookup the system ID associated to a public ID
- *
- * Returns the system ID if found or NULL otherwise.
- */
-const xmlChar *
-xmlCatalogGetXMLPublic(xmlCatalogEntryPtr catal, const xmlChar *pubID) {
-    const xmlChar *ret;
-    while (catal != NULL) {
-	switch (catal->type) {
-            case XML_CATA_CATALOG:
-		if (catal->children == NULL) {
-		    TODO /* fetch and fill */
-		}
-		ret = xmlCatalogGetXMLPublic(catal->children, pubID);
-		if (ret != NULL)
-		    return(ret);
-		break;
-            case XML_CATA_NEXT_CATALOG:
-		if (catal->children == NULL) {
-		    TODO /* fetch and fill */
-		}
-            case XML_CATA_PUBLIC:
-		if (xmlStrEqual(pubID, catal->name))
-		    return(catal->value);
-		break;
-            case XML_CATA_SYSTEM:
-            case XML_CATA_REWRITE_SYSTEM:
-            case XML_CATA_DELEGATE_PUBLIC:
-            case XML_CATA_DELEGATE_SYSTEM:
-            case XML_CATA_URI:
-            case XML_CATA_REWRITE_URI:
-            case XML_CATA_DELEGATE_URI:
-		TODO;
-		break;
-
-            case XML_CATA_NONE:
-            case SGML_CATA_SYSTEM:
-            case SGML_CATA_PUBLIC:
-            case SGML_CATA_ENTITY:
-            case SGML_CATA_PENTITY:
-            case SGML_CATA_DOCTYPE:
-            case SGML_CATA_LINKTYPE:
-            case SGML_CATA_NOTATION:
-            case SGML_CATA_DELEGATE:
-            case SGML_CATA_BASE:
-            case SGML_CATA_CATALOG:
-            case SGML_CATA_DOCUMENT:
-            case SGML_CATA_SGMLDECL:
-		/* Ignored entries */
-		break;
-	}
-	catal = catal->next;
-    }
-    return(NULL);
-}
-
-/**
- * xmlCatalogGetSGMLPublic:
- * @catal:  an SGML catalog hash
- * @pubId:  the public ID string
- *
- * Try to lookup the system ID associated to a public ID
- *
- * Returns the system ID if found or NULL otherwise.
- */
-static const xmlChar *
-xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
-    xmlCatalogEntryPtr entry;
-
-    if (catal == NULL)
-	return(NULL);
-
-    entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
-    if (entry == NULL)
-	return(NULL);
-    if (entry->type == SGML_CATA_PUBLIC)
-	return(entry->value);
-    return(NULL);
-}
-
-/**
  * xmlCatalogGetPublic:
  * @pubId:  the public ID string
  *
@@ -1335,6 +1638,25 @@
 }
 
 /**
+ * xmlCatalogResolve:
+ * @pubId:  the public ID string
+ * @sysId:  the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier
+ *
+ * Returns the URI of the resource or NULL if not found, it must be freed
+ *      by the caller.
+ */
+xmlChar *
+xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
+    if (xmlDefaultXMLCatalogList != NULL) {
+	return(xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, pubID, sysID));
+    } else {
+	return(xmlCatalogSGMLResolve(pubID, sysID));
+    }
+}
+
+/**
  * xmlCatalogDump:
  * @out:  the file.
  *
@@ -1373,7 +1695,7 @@
     } else if (xmlDefaultCatalog != NULL) {
 	xmlCatalogEntryType typ;
 
-	typ = xmlGetCatalogEntryType(type);
+	typ = xmlGetSGMLCatalogEntryType(type);
 	if (type != XML_CATA_NONE) {
 	    xmlCatalogEntryPtr entry;
 	    entry = xmlNewCatalogEntry(typ, orig, replace);
@@ -1393,6 +1715,14 @@
  */
 int
 xmlCatalogRemove(const xmlChar *value) {
+    int res = -1;
+
+    if (xmlDefaultXMLCatalogList != NULL) {
+	res = xmlDelXMLCatalog(xmlDefaultXMLCatalogList, value);
+    } else if (xmlDefaultCatalog != NULL) {
+	TODO
+    } 
+    return(res);
 }
 
 /**
diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am
index 9bf3248..38ad0ef 100644
--- a/include/libxml/Makefile.am
+++ b/include/libxml/Makefile.am
@@ -29,8 +29,7 @@
 		xmlversion.h \
 		xmlwin32version.h \
 		DOCBparser.h \
-		catalog.h \
-		trionan.h
+		catalog.h
 
 install-exec-hook:
 	$(mkinstalldirs) $(DESTDIR)$(xmlincdir) $(DESTDIR)$(xmlincdir)/libxml
diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h
index 1a62bb2..8651dfd 100644
--- a/include/libxml/catalog.h
+++ b/include/libxml/catalog.h
@@ -42,7 +42,7 @@
 void		xmlCatalogDump		(FILE *out);
 const xmlChar *	xmlCatalogGetSystem	(const xmlChar *sysID);
 const xmlChar *	xmlCatalogGetPublic	(const xmlChar *pubID);
-const xmlChar *	xmlCatalogResolve	(const xmlChar *pubID,
+xmlChar *	xmlCatalogResolve	(const xmlChar *pubID,
 	                                 const xmlChar *sysID);
 int		xmlCatalogAdd		(const xmlChar *type,
 					 const xmlChar *orig,
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 4b84cf6..de0bebb 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -471,18 +471,18 @@
 					 void *user_data,
 					 int depth,
 					 const xmlChar *string,
-					 xmlNodePtr *list);
+					 xmlNodePtr *lst);
 int		xmlParseExternalEntity	(xmlDocPtr doc,
 					 xmlSAXHandlerPtr sax,
 					 void *user_data,
 					 int depth,
 					 const xmlChar *URL,
 					 const xmlChar *ID,
-					 xmlNodePtr *list);
+					 xmlNodePtr *lst);
 int		xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx,
 					 const xmlChar *URL,
 					 const xmlChar *ID,
-					 xmlNodePtr *list);
+					 xmlNodePtr *lst);
 
 /*
  * SAX initialization routines
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 78cb0ca..8479056 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -295,6 +295,9 @@
 LIBXML_DLL_IMPORT extern double xmlXPathPINF;
 LIBXML_DLL_IMPORT extern double xmlXPathNINF;
 
+int		xmlXPathIsNaN	(double val);
+int		xmlXPathIsInf	(double val);
+
 /* These macros may later turn into functions */
 /**
  * xmlXPathNodeSetGetLength:
diff --git a/parser.c b/parser.c
index 9aa091c..64b55b5 100644
--- a/parser.c
+++ b/parser.c
@@ -8921,7 +8921,7 @@
  * @ctx:  the existing parsing context
  * @URL:  the URL for the entity to load
  * @ID:  the System ID for the entity to load
- * @list:  the return value for the set of parsed nodes
+ * @lst:  the return value for the set of parsed nodes
  *
  * Parse an external general entity within an existing parsing context
  * An external general parsed entity is well-formed if it matches the
@@ -8935,7 +8935,7 @@
 
 int
 xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
-	               const xmlChar *ID, xmlNodePtr *list) {
+	               const xmlChar *ID, xmlNodePtr *lst) {
     xmlParserCtxtPtr ctxt;
     xmlDocPtr newDoc;
     xmlSAXHandlerPtr oldsax = NULL;
@@ -8947,8 +8947,8 @@
 	return(XML_ERR_ENTITY_LOOP);
     }
 
-    if (list != NULL)
-        *list = NULL;
+    if (lst != NULL)
+        *lst = NULL;
     if ((URL == NULL) && (ID == NULL))
 	return(-1);
     if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
@@ -9065,7 +9065,7 @@
 	else
 	    ret = ctxt->errNo;
     } else {
-	if (list != NULL) {
+	if (lst != NULL) {
 	    xmlNodePtr cur;
 
 	    /*
@@ -9073,7 +9073,7 @@
 	     * they pseudo parent.
 	     */
 	    cur = newDoc->children->children;
-	    *list = cur;
+	    *lst = cur;
 	    while (cur != NULL) {
 		cur->parent = NULL;
 		cur = cur->next;
@@ -9282,7 +9282,7 @@
  * @depth:  Used for loop detection, use 0
  * @URL:  the URL for the entity to load
  * @ID:  the System ID for the entity to load
- * @list:  the return value for the set of parsed nodes
+ * @lst:  the return value for the set of parsed nodes
  *
  * Parse an external general entity
  * An external general parsed entity is well-formed if it matches the
@@ -9296,9 +9296,9 @@
 
 int
 xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
-	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) {
+	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
     return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
-		                       ID, list));
+		                       ID, lst));
 }
 
 /**
@@ -9308,7 +9308,7 @@
  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  * @depth:  Used for loop detection, use 0
  * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
- * @list:  the return value for the set of parsed nodes
+ * @lst:  the return value for the set of parsed nodes
  *
  * Parse a well-balanced chunk of an XML document
  * called by the parser
@@ -9323,7 +9323,7 @@
 
 int
 xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
-     void *user_data, int depth, const xmlChar *string, xmlNodePtr *list) {
+     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
     xmlParserCtxtPtr ctxt;
     xmlDocPtr newDoc;
     xmlSAXHandlerPtr oldsax = NULL;
@@ -9335,8 +9335,8 @@
     }
 
 
-    if (list != NULL)
-        *list = NULL;
+    if (lst != NULL)
+        *lst = NULL;
     if (string == NULL)
         return(-1);
 
@@ -9418,7 +9418,7 @@
 	else
 	    ret = ctxt->errNo;
     } else {
-	if (list != NULL) {
+	if (lst != NULL) {
 	    xmlNodePtr cur;
 
 	    /*
@@ -9426,7 +9426,7 @@
 	     * they pseudo parent.
 	     */
 	    cur = newDoc->children->children;
-	    *list = cur;
+	    *lst = cur;
 	    while (cur != NULL) {
 		cur->parent = NULL;
 		cur = cur->next;
diff --git a/trionan.c b/trionan.c
index d8bd99b..eae5225 100644
--- a/trionan.c
+++ b/trionan.c
@@ -200,7 +200,7 @@
 /*************************************************************************
  * trio_pinf
  */
-double
+TRIO_PUBLIC double
 trio_pinf(void)
 {
   /* Cache the result */
@@ -242,7 +242,7 @@
 /*************************************************************************
  * trio_ninf
  */
-double
+TRIO_PUBLIC double
 trio_ninf(void)
 {
   static double result = 0.0;
@@ -261,7 +261,7 @@
 /*************************************************************************
  * trio_nan
  */
-double
+TRIO_PUBLIC double
 trio_nan(void)
 {
   /* Cache the result */
@@ -306,7 +306,7 @@
 /*************************************************************************
  * trio_isnan
  */
-int
+TRIO_PUBLIC int
 trio_isnan(volatile double number)
 {
 #if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
@@ -370,7 +370,7 @@
 /*************************************************************************
  * trio_isinf
  */
-int
+TRIO_PUBLIC int
 trio_isinf(volatile double number)
 {
 #if defined(TRIO_COMPILER_DECC)
diff --git a/include/libxml/trionan.h b/trionan.h
similarity index 91%
rename from include/libxml/trionan.h
rename to trionan.h
index f955198..5b983b9 100644
--- a/include/libxml/trionan.h
+++ b/trionan.h
@@ -21,30 +21,40 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+#ifndef TRIO_PUBLIC
+#define TRIO_PUBLIC
+#endif
+
 /*
  * Return NaN (Not-a-Number).
  */
+TRIO_PUBLIC
 double trio_nan(void);
 
 /*
  * Return positive infinity.
  */
+TRIO_PUBLIC
 double trio_pinf(void);
 
 /*
  * Return negative infinity.
  */
+TRIO_PUBLIC
 double trio_ninf(void);
   
 /*
  * If number is a NaN return non-zero, otherwise return zero.
  */
+TRIO_PUBLIC
 int trio_isnan(double number);
 
 /*
  * If number is positive infinity return 1, if number is negative
  * infinity return -1, otherwise return 0.
  */
+TRIO_PUBLIC
 int trio_isinf(double number);
 
 #ifdef __cplusplus
diff --git a/xmlcatalog.c b/xmlcatalog.c
index 1a65450..7758519 100644
--- a/xmlcatalog.c
+++ b/xmlcatalog.c
@@ -26,7 +26,10 @@
 
 static int shell = 0;
 static int noout = 0;
+static int add = 0;
+static int del = 0;
 static int verbose = 0;
+static char *filename;
 
 #ifdef LIBXML_CATALOG_ENABLED
 /************************************************************************
@@ -74,8 +77,10 @@
     int nbargs;
     char command[100];
     char arg[400];
-    int i;
+    char *argv[20];
+    int i, ret;
     const xmlChar *answer;
+    xmlChar *ans;
 
     while (1) {
 	cmdline = xmlShellReadline("> ");
@@ -100,8 +105,9 @@
 	nbargs++;
 
 	/*
-	 * Parse the argument
+	 * Parse the argument string
 	 */
+	memset(arg, 0, sizeof(arg));
 	while ((*cur == ' ') || (*cur == '\t')) cur++;
 	i = 0;
 	while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
@@ -114,6 +120,46 @@
 	    nbargs++;
 
 	/*
+	 * Parse the arguments
+	 */
+	i = 0;
+	nbargs = 0;
+	cur = arg;
+	memset(argv, 0, sizeof(argv));
+	while (*cur != 0) {
+	    while ((*cur == ' ') || (*cur == '\t')) cur++;
+	    if (*cur == '\'') {
+		cur++;
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != '\'')) cur++;
+		if (*cur == '\'') {
+		    *cur = 0;
+		    nbargs++;
+		    i++;
+		    cur++;
+		}
+	    } else if (*cur == '"') { 
+		cur++;
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != '"')) cur++;
+		if (*cur == '"') {
+		    *cur = 0;
+		    nbargs++;
+		    i++;
+		    cur++;
+		}
+	    } else {
+		argv[i] = cur;
+		while ((*cur != 0) && (*cur != ' ') && (*cur != '\t'))
+		    cur++;
+		*cur = 0;
+		nbargs++;
+		i++;
+		cur++;
+	    }
+	}
+
+	/*
 	 * start interpreting the command
 	 */
         if (!strcmp(command, "exit"))
@@ -123,21 +169,68 @@
         if (!strcmp(command, "bye"))
 	    break;
 	if (!strcmp(command, "public")) {
-	    answer = xmlCatalogGetPublic((const xmlChar *) arg);
-	    if (answer == NULL) {
-		printf("No entry for PUBLIC %s\n", arg);
+	    if (nbargs != 1) {
+		printf("public requires 1 arguments\n");
 	    } else {
-		printf("%s\n", answer);
+		answer = xmlCatalogGetPublic((const xmlChar *) argv[0]);
+		if (answer == NULL) {
+		    printf("No entry for PUBLIC %s\n", argv[0]);
+		} else {
+		    printf("%s\n", answer);
+		}
 	    }
 	} else if (!strcmp(command, "system")) {
-	    answer = xmlCatalogGetSystem((const xmlChar *) arg);
-	    if (answer == NULL) {
-		printf("No entry for SYSTEM %s\n", arg);
+	    if (nbargs != 1) {
+		printf("system requires 1 arguments\n");
 	    } else {
-		printf("%s\n", answer);
+		answer = xmlCatalogGetSystem((const xmlChar *) argv[0]);
+		if (answer == NULL) {
+		    printf("No entry for SYSTEM %s\n", argv[0]);
+		} else {
+		    printf("%s\n", answer);
+		}
+	    }
+	} else if (!strcmp(command, "add")) {
+	    if ((nbargs != 3) && (nbargs != 2)) {
+		printf("add requires 2 or 3 arguments\n");
+	    } else {
+		if (argv[2] == NULL)
+		    ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
+			                BAD_CAST argv[1]);
+		else
+		    ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
+			                BAD_CAST argv[2]);
+		if (ret != 0)
+		    printf("add command failed\n");
+	    }
+	} else if (!strcmp(command, "del")) {
+	    if (nbargs != 1) {
+		printf("del requires 1\n");
+	    } else {
+		ret = xmlCatalogRemove(BAD_CAST argv[0]);
+		if (ret <= 0)
+		    printf("del command failed\n");
+
+	    }
+	} else if (!strcmp(command, "resolve")) {
+	    if (nbargs != 2) {
+		printf("resolve requires 2 arguments\n");
+	    } else {
+		ans = xmlCatalogResolve(BAD_CAST argv[0],
+			                BAD_CAST argv[1]);
+		if (ans == NULL) {
+		    printf("Resolver failed to find an answer\n");
+		} else {
+		    printf("%s\n", ans);
+		    xmlFree(ans);
+		}
 	    }
 	} else if (!strcmp(command, "dump")) {
-	    xmlCatalogDump(stdout);
+	    if (nbargs != 0) {
+		printf("dump has no arguments\n");
+	    } else {
+		xmlCatalogDump(stdout);
+	    }
 	} else {
 	    if (strcmp(command, "help")) {
 		printf("Unrecognized command %s\n", command);
@@ -145,6 +238,9 @@
 	    printf("Commands available:\n");
 	    printf("\tpublic PublicID: make a PUBLIC identifier lookup\n");
 	    printf("\tsystem SystemID: make a SYSTEM identifier lookup\n");
+	    printf("\tresolve PublicID SystemID: do a full resolver lookup\n");
+	    printf("\tadd 'type' 'orig' 'replace' : add an entry\n");
+	    printf("\tdel 'values' : remove values\n");
 	    printf("\tdump: print the current catalog state\n");
 	    printf("\texit:  quit the shell\n");
 	} 
@@ -158,9 +254,13 @@
  * 									*
  ************************************************************************/
 static void usage(const char *name) {
-    printf("Usage : %s [options] catalogfile ...\n", name);
-    printf("\tParse the catalog file(s) and output the result of the parsing\n");
+    printf("Usage : %s [options] catalogfile\n", name);
+    printf("\tParse the catalog file and output the result of the parsing\n");
     printf("\t--shell : run a shell allowing interactive queries\n");
+    printf("\t--add 'type' 'orig' 'replace' : add an entry\n");
+    printf("\t--del 'values' : remove values\n");
+    printf("\t--noout: avoid dumping the result on stdout\n");
+    printf("\t         used with add or del, it saves the catalog changes\n");
     printf("\t-v --verbose : provide debug informations\n");
 }
 int main(int argc, char **argv) {
@@ -183,10 +283,21 @@
 	    (!strcmp(argv[i], "--verbose"))) {
 	    verbose++;
 	    xmlCatalogSetDebug(verbose);
+	} else if ((!strcmp(argv[i], "-noout")) ||
+	    (!strcmp(argv[i], "--noout"))) {
+            noout = 1;
 	} else if ((!strcmp(argv[i], "-shell")) ||
 	    (!strcmp(argv[i], "--shell"))) {
 	    shell++;
             noout = 1;
+	} else if ((!strcmp(argv[i], "-add")) ||
+	    (!strcmp(argv[i], "--add"))) {
+	    i += 3;
+	    add++;
+	} else if ((!strcmp(argv[i], "-del")) ||
+	    (!strcmp(argv[i], "--del"))) {
+	    i += 1;
+	    del++;
 	} else {
 	    fprintf(stderr, "Unknown option %s\n", argv[i]);
 	    usage(argv[0]);
@@ -195,9 +306,60 @@
     }
 
     for (i = 1; i < argc; i++) {
-	if (argv[i][0] == '-')
+	if ((!strcmp(argv[i], "-add")) ||
+	    (!strcmp(argv[i], "--add"))) {
+	    i += 3;
 	    continue;
+	} else if ((!strcmp(argv[i], "-del")) ||
+	    (!strcmp(argv[i], "--del"))) {
+	    i += 1;
+	    continue;
+	} else if (argv[i][0] == '-')
+	    continue;
+	filename = argv[i];
 	xmlLoadCatalog(argv[i]);
+	break;
+    }
+
+    if ((add) || (del)) {
+	int ret;
+
+	for (i = 1; i < argc ; i++) {
+	    if (!strcmp(argv[i], "-"))
+		break;
+
+	    if (argv[i][0] != '-')
+		continue;
+	    if ((!strcmp(argv[i], "-add")) ||
+		(!strcmp(argv[i], "--add"))) {
+		if ((argv[i + 3] == NULL) || (argv[i + 3][0] == 0))
+		    ret = xmlCatalogAdd(BAD_CAST argv[i + 1], NULL,
+			                BAD_CAST argv[i + 2]);
+		else
+		    ret = xmlCatalogAdd(BAD_CAST argv[i + 1],
+			                BAD_CAST argv[i + 2],
+			                BAD_CAST argv[i + 3]);
+		if (ret != 0)
+		    printf("add command failed\n");
+		i += 3;
+	    } else if ((!strcmp(argv[i], "-del")) ||
+		(!strcmp(argv[i], "--del"))) {
+		ret = xmlCatalogRemove(BAD_CAST argv[i + 1]);
+		i += 1;
+	    }
+	}
+	
+	if (noout) {
+	    FILE *out;
+
+	    out = fopen(filename, "w");
+	    if (out == NULL) {
+		fprintf(stderr, "could not open %s for saving\n", filename);
+		noout = 0;
+	    } else {
+		xmlCatalogDump(out);
+	    }
+	}
     }
 
     if (shell) {
diff --git a/xpath.c b/xpath.c
index 984752a..b716fa6 100644
--- a/xpath.c
+++ b/xpath.c
@@ -51,7 +51,6 @@
 #include <libxml/debugXML.h>
 #endif
 #include <libxml/xmlerror.h>
-#include <libxml/trionan.h>
 
 /* #define DEBUG */
 /* #define DEBUG_STEP */
@@ -69,6 +68,9 @@
  * 									*
  ************************************************************************/
 
+#define TRIO_PUBLIC static
+#include "trionan.c"
+
 /*
  * The lack of portability of this section of the libc is annoying !
  */
@@ -94,6 +96,36 @@
     initialized = 1;
 }
 
+/**
+ * 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));
+}
+
+/**
+ * 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
+ */
+int
+xmlXPathIsInf(double val) {
+    return(trio_isinf(val));
+}
+
 /************************************************************************
  * 									*
  * 			Parser Types					*
@@ -526,7 +558,7 @@
 	    else fprintf(output, "false\n");
 	    break;
         case XPATH_NUMBER:
-	    switch (trio_isinf(cur->floatval)) {
+	    switch (xmlXPathIsInf(cur->floatval)) {
 	    case 1:
 		fprintf(output, "Object is a number : +Infinity\n");
 		break;
@@ -534,7 +566,7 @@
 		fprintf(output, "Object is a number : -Infinity\n");
 		break;
 	    default:
-		if (trio_isnan(cur->floatval)) {
+		if (xmlXPathIsNaN(cur->floatval)) {
 		    fprintf(output, "Object is a number : NaN\n");
 		} else {
 		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
@@ -1055,7 +1087,7 @@
 static void
 xmlXPathFormatNumber(double number, char buffer[], int buffersize)
 {
-    switch (trio_isinf(number)) {
+    switch (xmlXPathIsInf(number)) {
     case 1:
 	if (buffersize > (int)sizeof("+Infinity"))
 	    sprintf(buffer, "+Infinity");
@@ -1065,7 +1097,7 @@
 	    sprintf(buffer, "-Infinity");
 	break;
     default:
-	if (trio_isnan(number)) {
+	if (xmlXPathIsNaN(number)) {
 	    if (buffersize > (int)sizeof("NaN"))
 		sprintf(buffer, "NaN");
 	} else {
@@ -2813,7 +2845,7 @@
 xmlChar *
 xmlXPathCastNumberToString (double val) {
     xmlChar *ret;
-    switch (trio_isinf(val)) {
+    switch (xmlXPathIsInf(val)) {
     case 1:
 	ret = xmlStrdup((const xmlChar *) "+Infinity");
 	break;
@@ -2821,7 +2853,7 @@
 	ret = xmlStrdup((const xmlChar *) "-Infinity");
 	break;
     default:
-	if (trio_isnan(val)) {
+	if (xmlXPathIsNaN(val)) {
 	    ret = xmlStrdup((const xmlChar *) "NaN");
 	} else {
 	    /* could be improved */
@@ -3107,7 +3139,7 @@
  */
 int
 xmlXPathCastNumberToBoolean (double val) {
-     if (trio_isnan(val) || (val == 0.0))
+     if (xmlXPathIsNaN(val) || (val == 0.0))
 	 return(0);
      return(1);
 }
@@ -3714,13 +3746,13 @@
     }
     for (i = 0;i < ns1->nodeNr;i++) {
 	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
-	if (trio_isnan(val1))
+	if (xmlXPathIsNaN(val1))
 	    continue;
 	for (j = 0;j < ns2->nodeNr;j++) {
 	    if (init == 0) {
 		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
 	    }
-	    if (trio_isnan(values2[j]))
+	    if (xmlXPathIsNaN(values2[j]))
 		continue;
 	    if (inf && strict) 
 		ret = (val1 < values2[j]);
@@ -6177,9 +6209,9 @@
     CAST_TO_NUMBER;
     CHECK_TYPE(XPATH_NUMBER);
 
-    if ((trio_isnan(ctxt->value->floatval)) ||
-	(trio_isinf(ctxt->value->floatval) == 1) ||
-	(trio_isinf(ctxt->value->floatval) == -1) ||
+    if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
+	(xmlXPathIsInf(ctxt->value->floatval) == 1) ||
+	(xmlXPathIsInf(ctxt->value->floatval) == -1) ||
 	(ctxt->value->floatval == 0.0))
 	return;