patch from Richard Jinks for XPath substring() function new set of tests

* xpath.c: patch from Richard Jinks for XPath substring() function
* result/XPath/expr/strings test/XPath/expr/strings: new set of tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index 70f2f9a..eb46a0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jun 10 18:00:02 CEST 2002 Daniel Veillard <daniel@veillard.com>
+
+	* xpath.c: patch from Richard Jinks for XPath substring() function
+	* result/XPath/expr/strings test/XPath/expr/strings: new set of tests
+
 2002-06-06  Aleksey Sanin  <set EMAIL_ADDRESS environment variable>
 
 	* xmlIO.c: patch from Rachel Hestilow to fix bug #84340
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 33e511c..28dacf4 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -822,6 +822,9 @@
 					 int * doc_txt_len,
 					 const char *txt_encoding,
 					 int format);
+int		xmlDocFormatDump(FILE *f,
+					 xmlDocPtr cur,
+					 int format);
 int		xmlDocDump		(FILE *f,
 					 xmlDocPtr cur);
 void		xmlElemDump		(FILE *f,
diff --git a/result/XPath/expr/strings b/result/XPath/expr/strings
index 5ccd7c2..fad7048 100644
--- a/result/XPath/expr/strings
+++ b/result/XPath/expr/strings
@@ -68,27 +68,63 @@
 Object is a string : 2345
 
 ========================
+Expression: substring("12345",-4)
+Object is a string : 12345
+
+========================
+Expression: substring("12345",3.4)
+Object is a string : 345
+
+========================
+Expression: substring("12345",3.6)
+Object is a string : 45
+
+========================
 Expression: substring("12345",1.5,2.6)
 Object is a string : 234
 
 ========================
+Expression: substring("12345",2.2,2.2)
+Object is a string : 23
+
+========================
 Expression: substring("12345",0,3)
 Object is a string : 12
 
 ========================
-Expression: substring("12345", 0 div 0, 3)
+Expression: substring("12345",-8,10)
+Object is a string : 1
+
+========================
+Expression: substring("12345",4,-10)
 Object is a string : 
 
 ========================
-Expression: substring("12345", 1, 0 div 0)
+Expression: substring("12345",0 div 0, 3)
 Object is a string : 
 
 ========================
-Expression: substring("12345", -42, 1 div 0)
+Expression: substring("12345",1, 0 div 0)
+Object is a string : 
+
+========================
+Expression: substring("12345",1 div 0, 3)
+Object is a string : 
+
+========================
+Expression: substring("12345",3,-1 div 0)
+Object is a string : 
+
+========================
+Expression: substring("12345",-42, 1 div 0)
 Object is a string : 12345
 
 ========================
-Expression: substring("12345", -1 div 0, 1 div 0)
+Expression: substring("12345",-1 div 0, 1 div 0)
+Object is a string : 
+
+========================
+Expression: substring("12345",-1 div 0,5)
 Object is a string : 
 
 ========================
diff --git a/test/XPath/expr/strings b/test/XPath/expr/strings
index a070f3a..849ca14 100644
--- a/test/XPath/expr/strings
+++ b/test/XPath/expr/strings
@@ -15,11 +15,20 @@
 contains("tititototata","tita")
 substring("12345",2,3)
 substring("12345",2)
+substring("12345",-4)
+substring("12345",3.4)
+substring("12345",3.6)
 substring("12345",1.5,2.6)
+substring("12345",2.2,2.2)
 substring("12345",0,3)
-substring("12345", 0 div 0, 3)
-substring("12345", 1, 0 div 0)
-substring("12345", -42, 1 div 0)
-substring("12345", -1 div 0, 1 div 0)
+substring("12345",-8,10)
+substring("12345",4,-10)
+substring("12345",0 div 0, 3)
+substring("12345",1, 0 div 0)
+substring("12345",1 div 0, 3)
+substring("12345",3,-1 div 0)
+substring("12345",-42, 1 div 0)
+substring("12345",-1 div 0, 1 div 0)
+substring("12345",-1 div 0,5)
 string-length("")
 string-length("titi")
diff --git a/tree.c b/tree.c
index c8959f6..b4b143b 100644
--- a/tree.c
+++ b/tree.c
@@ -6986,16 +6986,17 @@
 }
 
 /**
- * xmlDocDump:
+ * xmlDocFormatDump:
  * @f:  the FILE*
  * @cur:  the document
+ * @format: should formatting spaces been added
  *
  * Dump an XML document to an open FILE.
  *
  * returns: the number of bytes written or -1 in case of failure.
  */
 int
-xmlDocDump(FILE *f, xmlDocPtr cur) {
+xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
     xmlOutputBufferPtr buf;
     const char * encoding;
     xmlCharEncodingHandlerPtr handler = NULL;
@@ -7030,13 +7031,27 @@
     }
     buf = xmlOutputBufferCreateFile(f, handler);
     if (buf == NULL) return(-1);
-    xmlDocContentDumpOutput(buf, cur, NULL, 0);
+    xmlDocContentDumpOutput(buf, cur, NULL, format);
 
     ret = xmlOutputBufferClose(buf);
     return(ret);
 }
 
 /**
+ * xmlDocDump:
+ * @f:  the FILE*
+ * @cur:  the document
+ *
+ * Dump an XML document to an open FILE.
+ *
+ * returns: the number of bytes written or -1 in case of failure.
+ */
+int
+xmlDocDump(FILE *f, xmlDocPtr cur) {
+	return(xmlDocFormatDump (f, cur, 0));
+}
+
+/**
  * xmlSaveFileTo:
  * @buf:  an output I/O buffer
  * @cur:  the document
diff --git a/xmlIO.c b/xmlIO.c
index 949d9c6..a540c06 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -143,6 +143,7 @@
         xmlInputCallbackTable[i].readcallback = NULL;
         xmlInputCallbackTable[i].closecallback = NULL;
     }
+    xmlInputCallbackInitialized = 0;
 
     xmlInputCallbackNr = 0;
     xmlInputCallbackInitialized = 0;
@@ -168,6 +169,7 @@
         xmlOutputCallbackTable[i].writecallback = NULL;
         xmlOutputCallbackTable[i].closecallback = NULL;
     }
+    xmlOutputCallbackInitialized = 0;
 
     xmlOutputCallbackNr = 0;
     xmlOutputCallbackInitialized = 0;
@@ -2116,7 +2118,7 @@
     int res = 0;
     int nbchars = 0;
     int buffree;
-    int needSize;
+    unsigned int needSize;
 
     if ((len <= MINLEN) && (len != 4)) 
         len = MINLEN;
diff --git a/xpath.c b/xpath.c
index c166c82..f4f79b3 100644
--- a/xpath.c
+++ b/xpath.c
@@ -6162,37 +6162,47 @@
     /*
      * If last pos not present, calculate last position
     */
-    if (nargs != 3)
-	le = m;
+    if (nargs != 3) {
+	le = (double)m;
+	if (in < 1.0) 
+	    in = 1.0;
+    }
 
     /* Need to check for the special cases where either 
      * the index is NaN, the length is NaN, or both
      * arguments are infinity (relying on Inf + -Inf = NaN)
      */
-    if (!xmlXPathIsNaN(in + le)) {
+    if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) {
         /*
-         * To meet our requirements, initial index calculations
-         * must be done before we convert to integer format
+         * To meet the requirements of the spec, the arguments
+	 * must be converted to integer format before 
+	 * initial index calculations are done
          *
-         * First we normalize indices
-         */
-        in -= 1.0;
-        le += in;
-        if (in < 0.0)
-            in = 0.0;
-        if (le > (double)m)
-            le = (double)m;
-
-        /*
-         * Now we go to integer form, rounding up
+         * First we go to integer form, rounding up
+	 * and checking for special cases
          */
         i = (int) in;
-        if (((double)i) != in) i++;
-    
-        l = (int) le;
-        if (((double)l) != le) l++;
+        if (((double)i)+0.5 <= in) i++;
 
-        if (l > m) l=m;
+	if (xmlXPathIsInf(le) == 1) {
+	    l = m;
+	    if (i < 1)
+		i = 1;
+	}
+	else if (xmlXPathIsInf(le) == -1 || le < 0.0)
+	    l = 0;
+	else {
+	    l = (int) le;
+	    if (((double)l)+0.5 <= le) l++;
+	}
+
+	/* Now we normalize inidices */
+        i -= 1;
+        l += i;
+        if (i < 0)
+            i = 0;
+        if (l > m)
+            l = m;
 
         /* number of chars to copy */
         l -= i;