Bug fixes new Xinclude tests:
- nanoftp.c: fixed gcc 2.95 new warnings
- SAX.c: fixed a stupid bug
- tree.c: fixed a formatting problem when round-tripping
  from/to memory
- xinclude.c: chased memleak, fixed a base problem
- xpointer.c: added xmlXPtrBuildRangeNodeList(), finished ?
  xmlXPtrBuildNodeList()
- TODO: updated
- Makefile.am test/XInclude/docs test/XInclude/ents result/XInclude:
  adding a first small set of regression tests for XInclude
Daniel
diff --git a/ChangeLog b/ChangeLog
index d530e9a..53a0ad5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Sun Nov 12 16:31:19 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* nanoftp.c: fixed gcc 2.95 new warnings
+	* SAX.c: fixed a stupid bug
+	* tree.c: fixed a formatting problem when round-tripping
+	  from/to memory
+	* xinclude.c: chased memleak, fixed a base problem
+	* xpointer.c: added xmlXPtrBuildRangeNodeList(), finished ? 
+	  xmlXPtrBuildNodeList()
+	* TODO: updated
+	* Makefile.am test/XInclude/docs test/XInclude/ents result/XInclude:
+	  adding a first small set of regression tests for XInclude
+
 Tue Nov  7 15:11:34 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
 
 	* nanohttp.[ch]: applied Wayne Davison patches to access
diff --git a/Makefile.am b/Makefile.am
index 56aa3ff..4367b24 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,7 +82,7 @@
 
 testall : tests SVGtests SAXtests
 
-tests: XMLtests XMLenttests HTMLtests Validtests URItests XPathtests XPtrtests
+tests: XMLtests XMLenttests HTMLtests Validtests URItests XPathtests XPtrtests XIncludetests
 
 HTMLtests : testHTML
 	@(rm -f .memdump ; touch .memdump)
@@ -273,6 +273,24 @@
 	      rm result.$$name ; \
 	  fi ; fi ; done ; fi ; done)
 
+XIncludetests : xmllint
+	@echo "##"
+	@echo "## XInclude regression tests"
+	@echo "##"
+	@(for i in $(srcdir)/test/XInclude/docs/* ; do \
+	  name=`basename $$i`; \
+	  if [ ! -d $$i ] ; then \
+	  if [ ! -f $(srcdir)/result/XInclude/$$name ] ; then \
+	      echo New test file $$name ; \
+	      $(top_builddir)/xmllint --xinclude $$i > $(srcdir)/result/XInclude/$$name ; \
+	  else \
+	      echo Testing $$name ; \
+	      $(top_builddir)/xmllint --xinclude $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
+	      diff $(srcdir)/result/XInclude/$$name result.$$name ; \
+	      rm result.$$name ; \
+	  fi ; fi ; done)
+
 SVGtests : xmllint
 	@echo "##"
 	@echo "## SVG parsing regression tests"
diff --git a/SAX.c b/SAX.c
index 168eb46..8483c2f 100644
--- a/SAX.c
+++ b/SAX.c
@@ -1668,7 +1668,7 @@
     htmlDefaultSAXHandler.endElement = endElement;
     htmlDefaultSAXHandler.reference = NULL;
     htmlDefaultSAXHandler.characters = characters;
-    xmlDefaultSAXHandler.cdataBlock = cdataBlock;
+    htmlDefaultSAXHandler.cdataBlock = cdataBlock;
     htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
     htmlDefaultSAXHandler.processingInstruction = NULL;
     htmlDefaultSAXHandler.comment = comment;
diff --git a/TODO b/TODO
index a6155ff..61ba935 100644
--- a/TODO
+++ b/TODO
@@ -6,6 +6,8 @@
 TODO:
 =====
 
+- Computation of base when HTTP redirect occurs, might affect HTTP
+  interfaces.
 - performances: there is still improvements needed when parsing Docbook DTD
   a single function to optimize/avoid.
 - DOM needs
diff --git a/nanoftp.c b/nanoftp.c
index c5e7acb..1207355 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -1310,7 +1310,7 @@
 	}
 	cur = &ctxt->controlBuf[ctxt->controlBufAnswer]; 
 	while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;
-	if (sscanf(cur, "%d,%d,%d,%d,%d,%d", &temp[0], &temp[1], &temp[2],
+	if (sscanf(cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
 	            &temp[3], &temp[4], &temp[5]) != 6) {
 	    xmlGenericError(xmlGenericErrorContext,
 		    "Invalid answer to PASV\n");
diff --git a/result/XInclude/include.xml b/result/XInclude/include.xml
new file mode 100644
index 0000000..e03b385
--- /dev/null
+++ b/result/XInclude/include.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including another XML document -->
+   <doc>
+<p>something</p>
+<p>really</p>
+<p>simple</p>
+</doc>
+</x>
diff --git a/result/XInclude/nodes.xml b/result/XInclude/nodes.xml
new file mode 100644
index 0000000..5de8cec
--- /dev/null
+++ b/result/XInclude/nodes.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including a set of nodes from an XML document -->
+   <p>something</p><p>really</p><p>simple</p>
+</x>
diff --git a/result/XInclude/txtinclude.xml b/result/XInclude/txtinclude.xml
new file mode 100644
index 0000000..b6c91c7
--- /dev/null
+++ b/result/XInclude/txtinclude.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including another text document -->
+   this is some text in ASCII
+
+</x>
diff --git a/test/XInclude/docs/include.xml b/test/XInclude/docs/include.xml
new file mode 100644
index 0000000..5365364
--- /dev/null
+++ b/test/XInclude/docs/include.xml
@@ -0,0 +1,4 @@
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including another XML document -->
+   <xinclude:include href="../ents/something.xml"/>
+</x>
diff --git a/test/XInclude/docs/nodes.xml b/test/XInclude/docs/nodes.xml
new file mode 100644
index 0000000..df2da4a
--- /dev/null
+++ b/test/XInclude/docs/nodes.xml
@@ -0,0 +1,4 @@
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including a set of nodes from an XML document -->
+   <xinclude:include href="../ents/something.xml#xpointer(//p)"/>
+</x>
diff --git a/test/XInclude/docs/txtinclude.xml b/test/XInclude/docs/txtinclude.xml
new file mode 100644
index 0000000..e8e5041
--- /dev/null
+++ b/test/XInclude/docs/txtinclude.xml
@@ -0,0 +1,4 @@
+<x xmlns:xinclude="http://www.w3.org/1999/XML/xinclude">
+   <!-- Simple test of including another text document -->
+   <xinclude:include href="../ents/something.txt" parse="text"/>
+</x>
diff --git a/test/XInclude/ents/something.txt b/test/XInclude/ents/something.txt
new file mode 100644
index 0000000..48c21b7
--- /dev/null
+++ b/test/XInclude/ents/something.txt
@@ -0,0 +1 @@
+this is some text in ASCII
diff --git a/test/XInclude/ents/something.xml b/test/XInclude/ents/something.xml
new file mode 100644
index 0000000..9bba683
--- /dev/null
+++ b/test/XInclude/ents/something.xml
@@ -0,0 +1,5 @@
+<doc>
+<p>something</p>
+<p>really</p>
+<p>simple</p>
+</doc>
diff --git a/tree.c b/tree.c
index 5fd26b5..708ff01 100644
--- a/tree.c
+++ b/tree.c
@@ -5119,7 +5119,7 @@
         xmlNodePtr child = cur->children;
 
 	while (child != NULL) {
-	    xmlNodeDump(buf, cur, child, 0, 1);
+	    xmlNodeDump(buf, cur, child, 0, 0);
 	    xmlBufferWriteChar(buf, "\n");
 	    child = child->next;
 	}
@@ -5218,16 +5218,6 @@
     }
     xmlOutputBufferWriteString(buf, " [\n");
     xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
-#if 0
-    if (dtd->entities != NULL)
-	xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
-    if (dtd->notations != NULL)
-	xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
-    if (dtd->elements != NULL)
-	xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
-    if (dtd->attributes != NULL)
-	xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
-#endif
     xmlOutputBufferWriteString(buf, "]>");
 }
 
diff --git a/xinclude.c b/xinclude.c
index a5510f7..c377f64 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -396,6 +396,7 @@
 	    xmlGenericError(xmlGenericErrorContext,
 			"XInclude: XPointer evaluation failed: #%s\n",
 			fragment);
+	    xmlXPathFreeContext(xptrctxt);
 	    xmlFree(URL);
 	    xmlFree(fragment);
 	    return;
@@ -599,7 +600,11 @@
      * compute the URI
      */
     base = xmlNodeGetBase(ctxt->doc, cur);
-    URI = xmlBuildURI(href, base);
+    if (base == NULL) {
+	URI = xmlBuildURI(href, ctxt->doc->URL);
+    } else {
+	URI = xmlBuildURI(href, base);
+    }
     if (URI == NULL) {
 	xmlChar *escbase;
 	xmlChar *eschref;
diff --git a/xpointer.c b/xpointer.c
index 7eaf49f..7ead4b7 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -55,6 +55,7 @@
  *									*
  ************************************************************************/
 
+xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur);
 /**
  * xmlXPtrGetArity:
  * @cur:  the node
@@ -1302,13 +1303,182 @@
 }
 
 /**
+ * xmlXPtrBuildRangeNodeList:
+ * @range:  a range object
+ *
+ * Build a node list tree copy of the range
+ *
+ * Returns an xmlNodePtr list or NULL.
+ *         the caller has to free the node tree.
+ */
+xmlNodePtr
+xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
+    /* pointers to generated nodes */
+    xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp;
+    /* pointers to traversal nodes */
+    xmlNodePtr start, cur, end;
+    int index, index2;
+
+    if (range == NULL)
+	return(NULL);
+    if (range->type != XPATH_RANGE)
+	return(NULL);
+    start = (xmlNodePtr) range->user;
+
+    if (start == NULL)
+	return(NULL);
+    end = range->user2;
+    if (end == NULL)
+	return(xmlCopyNode(start, 1));
+
+    cur = start;
+    index = range->index;
+    index2 = range->index2;
+    while (cur != NULL) {
+	if (cur == end) {
+	    if (cur->type == XML_TEXT_NODE) {
+		const xmlChar *content = cur->content;
+		int len;
+
+		if (content == NULL) {
+		    tmp = xmlNewTextLen(NULL, 0);
+		} else {
+		    len = index2;
+		    if ((cur == start) && (index > 1)) {
+			content += (index - 1);
+			len -= (index - 1);
+			index = 0;
+		    } else {
+			len = index2;
+		    }
+		    tmp = xmlNewTextLen(content, len);
+		}
+		/* single sub text node selection */
+		if (list == NULL)
+		    return(tmp);
+		/* prune and return full set */
+		if (last != NULL)
+		    xmlAddNextSibling(last, tmp);
+		else 
+		    xmlAddChild(parent, tmp);
+		return(list);
+	    } else {
+		tmp = xmlCopyNode(cur, 0);
+		if (list == NULL)
+		    list = tmp;
+		else {
+		    if (last != NULL)
+			xmlAddNextSibling(last, tmp);
+		    else
+			xmlAddChild(parent, tmp);
+		}
+		last = NULL;
+		parent = tmp;
+
+		if (index2 > 1) {
+		    end = xmlXPtrGetNthChild(cur, index2 - 1);
+		    index2 = 0;
+		}
+		if ((cur == start) && (index > 1)) {
+		    cur = xmlXPtrGetNthChild(cur, index - 1);
+		    index = 0;
+		} else {
+		    cur = cur->children;
+		}
+		/*
+		 * Now gather the remaining nodes from cur to end
+		 */
+		continue; /* while */
+	    }
+	} else if ((cur == start) &&
+		   (list == NULL) /* looks superfluous but ... */ ) {
+	    if (cur->type == XML_TEXT_NODE) {
+		const xmlChar *content = cur->content;
+
+		if (content == NULL) {
+		    tmp = xmlNewTextLen(NULL, 0);
+		} else {
+		    if (index > 1) {
+			content += (index - 1);
+		    }
+		    tmp = xmlNewText(content);
+		}
+		last = list = tmp;
+	    } else {
+		if ((cur == start) && (index > 1)) {
+		    tmp = xmlCopyNode(cur, 0);
+		    list = tmp;
+		    parent = tmp;
+		    last = NULL;
+		    cur = xmlXPtrGetNthChild(cur, index - 1);
+		    index = 0;
+		    /*
+		     * Now gather the remaining nodes from cur to end
+		     */
+		    continue; /* while */
+		}
+		tmp = xmlCopyNode(cur, 1);
+		list = tmp;
+		parent = NULL;
+		last = tmp;
+	    }
+	} else {
+	    tmp = NULL;
+	    switch (cur->type) {
+		case XML_DTD_NODE:
+		case XML_ELEMENT_DECL:
+		case XML_ATTRIBUTE_DECL:
+		case XML_ENTITY_NODE:
+		    /* Do not copy DTD informations */
+		    break;
+		case XML_ENTITY_DECL:
+		    TODO /* handle csossing entities -> stack needed */
+		    break;
+		case XML_XINCLUDE_START:
+		case XML_XINCLUDE_END:
+		    /* don't consider it part of the tree content */
+		    break;
+		case XML_ATTRIBUTE_NODE:
+		    /* Humm, should not happen ! */
+		    STRANGE
+		    break;
+		default:
+		    tmp = xmlCopyNode(cur, 1);
+		    break;
+	    }
+	    if (tmp != NULL) {
+		if ((list == NULL) || ((last == NULL) && (parent == NULL)))  {
+		    STRANGE
+		    return(NULL);
+		}
+		if (last != NULL)
+		    xmlAddNextSibling(last, tmp);
+		else {
+		    xmlAddChild(parent, tmp);
+		    last = tmp;
+		}
+	    }
+	}
+	/*
+	 * Skip to next node in document order
+	 */
+	if ((list == NULL) || ((last == NULL) && (parent == NULL)))  {
+	    STRANGE
+	    return(NULL);
+	}
+	cur = xmlXPtrAdvanceNode(cur);
+    }
+    return(list);
+}
+
+/**
  * xmlXPtrBuildNodeList:
  * @obj:  the XPointer result from the evaluation.
  *
- * Build a node list copy of the XPointer result.
+ * Build a node list tree copy of the XPointer result.
  *
  * Returns an xmlNodePtr list or NULL.
- *         the caller has to free the node list.
+ *         the caller has to free the node tree.
  */
 xmlNodePtr
 xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) {
@@ -1333,8 +1503,27 @@
 	    }
 	    break;
 	}
-	case XPATH_LOCATIONSET:
+	case XPATH_LOCATIONSET: {
+	    xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
+	    if (set == NULL)
+		return(NULL);
+	    for (i = 0;i < set->locNr;i++) {
+		if (last == NULL)
+		    list = last = xmlXPtrBuildNodeList(set->locTab[i]);
+		else
+		    xmlAddNextSibling(last,
+			    xmlXPtrBuildNodeList(set->locTab[i]));
+		if (last != NULL) {
+		    while (last->next != NULL)
+			last = last->next;
+		}
+	    }
 	    break;
+	}
+	case XPATH_RANGE:
+	    return(xmlXPtrBuildRangeNodeList(obj));
+	case XPATH_POINT:
+	    return(xmlCopyNode(obj->user, 0));
 	default:
 	    break;
     }