More work and fixes on XPath:
- debugXML.c testXPath.c xpath.[ch]: More work on XPath/Xpointer,
  incorporated "(TOM)" <ptittom@free.fr> patches rebuilt the XPath
  examples with the extra test
Daniel
diff --git a/ChangeLog b/ChangeLog
index 70c747d..1767545 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed Oct  4 15:25:53 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* debugXML.c testXPath.c xpath.[ch]: More work on XPath/Xpointer,
+	  incorporated "(TOM)" <ptittom@free.fr> patches rebuilt the XPath
+	  examples with the extra test
+
 Wed Oct  4 14:39:01 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
 
 	* parser.c xmlIO.c xmlIO.h: fixed bug 26650, and improved
diff --git a/debugXML.c b/debugXML.c
index 0363352..f2178de 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -584,6 +584,8 @@
 	xmlDebugDumpAttrList(output, node->properties, depth + 1);
     if (node->type != XML_ENTITY_REF_NODE) {
 	if (node->content != NULL) {
+            shift[2 * i] = shift[2 * i + 1] = ' ' ;
+            shift[2 * i + 2] = shift[2 * i + 3] = 0 ;
 	    fprintf(output, shift);
 	    fprintf(output, "content=");
 #ifndef XML_USE_BUFFER_CONTENT	    
@@ -1681,6 +1683,18 @@
 			case XPATH_STRING:
 			    fprintf(stderr, "%s is a string\n", arg);
 			    break;
+			case XPATH_POINT:
+			    fprintf(stderr, "%s is a point\n", arg);
+			    break;
+			case XPATH_RANGE:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_LOCATIONSET:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_USERS:
+			    fprintf(stderr, "%s is user-defined\n", arg);
+			    break;
 		    }
 		    xmlXPathFreeNodeSetList(list);
 		} else {
@@ -1719,6 +1733,18 @@
 			case XPATH_STRING:
 			    fprintf(stderr, "%s is a string\n", arg);
 			    break;
+			case XPATH_POINT:
+			    fprintf(stderr, "%s is a point\n", arg);
+			    break;
+			case XPATH_RANGE:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_LOCATIONSET:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_USERS:
+			    fprintf(stderr, "%s is user-defined\n", arg);
+			    break;
 		    }
 		    xmlXPathFreeNodeSetList(list);
 		} else {
@@ -1761,6 +1787,18 @@
 			case XPATH_STRING:
 			    fprintf(stderr, "%s is a string\n", arg);
 			    break;
+			case XPATH_POINT:
+			    fprintf(stderr, "%s is a point\n", arg);
+			    break;
+			case XPATH_RANGE:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_LOCATIONSET:
+			    fprintf(stderr, "%s is a range\n", arg);
+			    break;
+			case XPATH_USERS:
+			    fprintf(stderr, "%s is user-defined\n", arg);
+			    break;
 		    }
 		    xmlXPathFreeNodeSetList(list);
 		} else {
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 6c5f42e..631f59f 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -51,7 +51,10 @@
     XPATH_BOOLEAN = 2,
     XPATH_NUMBER = 3,
     XPATH_STRING = 4,
-    XPATH_USERS = 5
+    XPATH_POINT = 5,
+    XPATH_RANGE = 6,
+    XPATH_LOCATIONSET = 7,
+    XPATH_USERS = 8
 } xmlXPathObjectType;
 
 typedef struct _xmlXPathObject xmlXPathObject;
@@ -63,6 +66,9 @@
     double floatval;
     xmlChar *stringval;
     void *user;
+    int index;
+    void *user2;
+    int index2;
 };
 
 /*
@@ -168,6 +174,11 @@
     /* extra variables */
     int contextSize;			/* the context size */
     int proximityPosition;		/* the proximity position */
+
+    /* extra stuff for XPointer */
+    int xptr;				/* it this an XPointer context */
+    xmlNodePtr here;			/* for here() */
+    xmlNodePtr origin;			/* for origin() */
 };
 
 /*
@@ -220,10 +231,13 @@
 /**
  * Evaluation functions.
  */
+void		   xmlXPathInit			(void);
 xmlXPathContextPtr xmlXPathNewContext		(xmlDocPtr doc);
 void		   xmlXPathFreeContext		(xmlXPathContextPtr ctxt);
 xmlXPathObjectPtr  xmlXPathEval			(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);
+xmlXPathObjectPtr  xmlXPathEvalXPtrExpr		(const xmlChar *str,
+						 xmlXPathContextPtr ctxt);
 void		   xmlXPathFreeObject		(xmlXPathObjectPtr obj);
 xmlXPathObjectPtr  xmlXPathEvalExpression	(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);
diff --git a/result/XPath/expr/base b/result/XPath/expr/base
index 2f1ebda..3552866 100644
--- a/result/XPath/expr/base
+++ b/result/XPath/expr/base
@@ -1,5 +1,20 @@
+
+========================
+Expression: 1
 Object is a number : 1
+
+========================
+Expression: 1+2
 Object is a number : 3
+
+========================
+Expression: 2*3
 Object is a number : 6
+
+========================
+Expression: 1+2*3+4
 Object is a number : 11
+
+========================
+Expression: (1+2)*(3+4)
 Object is a number : 21
diff --git a/result/XPath/expr/compare b/result/XPath/expr/compare
index daae1a2..a0dcdc4 100644
--- a/result/XPath/expr/compare
+++ b/result/XPath/expr/compare
@@ -1,24 +1,96 @@
+
+========================
+Expression: 0<1
 Object is a Boolean : true
+
+========================
+Expression: 0<=1
 Object is a Boolean : true
+
+========================
+Expression: 0>1
 Object is a Boolean : false
+
+========================
+Expression: 0>=1
 Object is a Boolean : false
+
+========================
+Expression: 1<0
 Object is a Boolean : false
+
+========================
+Expression: 1<=0
 Object is a Boolean : false
+
+========================
+Expression: 1>0
 Object is a Boolean : true
+
+========================
+Expression: 1>=0
 Object is a Boolean : true
+
+========================
+Expression: 1<1
 Object is a Boolean : false
+
+========================
+Expression: 1<=1
 Object is a Boolean : true
+
+========================
+Expression: 1>1
 Object is a Boolean : false
+
+========================
+Expression: 1>=1
 Object is a Boolean : true
+
+========================
+Expression: '0'<1
 Object is a Boolean : true
+
+========================
+Expression: '0'<=1
 Object is a Boolean : true
+
+========================
+Expression: '0'>1
 Object is a Boolean : false
+
+========================
+Expression: '0'>=1
 Object is a Boolean : false
+
+========================
+Expression: 0<'1.2'
 Object is a Boolean : true
+
+========================
+Expression: 0<='1.2'
 Object is a Boolean : true
+
+========================
+Expression: 0>'1.2'
 Object is a Boolean : false
+
+========================
+Expression: 0>='1.2'
 Object is a Boolean : false
+
+========================
+Expression: false()<1
 Object is a Boolean : true
+
+========================
+Expression: false()<=1
 Object is a Boolean : true
+
+========================
+Expression: 0>true()
 Object is a Boolean : false
+
+========================
+Expression: 0>=true()
 Object is a Boolean : false
diff --git a/result/XPath/expr/equality b/result/XPath/expr/equality
index 92d6d1c..594b101 100644
--- a/result/XPath/expr/equality
+++ b/result/XPath/expr/equality
@@ -1,24 +1,96 @@
+
+========================
+Expression: 1=1
 Object is a Boolean : true
+
+========================
+Expression: 1!=1
 Object is a Boolean : false
+
+========================
+Expression: 1=0
 Object is a Boolean : false
+
+========================
+Expression: 1!=0
 Object is a Boolean : true
+
+========================
+Expression: true()=true()
 Object is a Boolean : true
+
+========================
+Expression: true()!=true()
 Object is a Boolean : false
+
+========================
+Expression: true()=false()
 Object is a Boolean : false
+
+========================
+Expression: false()!=true()
 Object is a Boolean : true
+
+========================
+Expression: 'test'='test'
 Object is a Boolean : true
+
+========================
+Expression: 'test'!='test'
 Object is a Boolean : false
+
+========================
+Expression: 'test2'='test'
 Object is a Boolean : false
+
+========================
+Expression: 'test2'!='test'
 Object is a Boolean : true
+
+========================
+Expression: false()=0
 Object is a Boolean : true
+
+========================
+Expression: false()!=0
 Object is a Boolean : false
+
+========================
+Expression: false()=1
 Object is a Boolean : false
+
+========================
+Expression: false()!=1
 Object is a Boolean : true
+
+========================
+Expression: 0=true()
 Object is a Boolean : false
+
+========================
+Expression: 0!=true()
 Object is a Boolean : true
+
+========================
+Expression: 1=true()
 Object is a Boolean : true
+
+========================
+Expression: 1!=true()
 Object is a Boolean : false
+
+========================
+Expression: true()='test'
 Object is a Boolean : true
+
+========================
+Expression: false()='test'
 Object is a Boolean : false
+
+========================
+Expression: 'test'!=true()
 Object is a Boolean : false
+
+========================
+Expression: 'test'!=false()
 Object is a Boolean : true
diff --git a/result/XPath/expr/functions b/result/XPath/expr/functions
index 3e40603..29f44f7 100644
--- a/result/XPath/expr/functions
+++ b/result/XPath/expr/functions
@@ -1,5 +1,20 @@
+
+========================
+Expression: true()
 Object is a Boolean : true
+
+========================
+Expression: false()
 Object is a Boolean : false
+
+========================
+Expression: number("1.5")
 Object is a number : 1.5
+
+========================
+Expression: concat("titi",'toto')
 Object is a string : tititoto
+
+========================
+Expression: concat("titi",'toto',"tata","last")
 Object is a string : tititototatalast
diff --git a/result/XPath/expr/strings b/result/XPath/expr/strings
index e405715..85a35c9 100644
--- a/result/XPath/expr/strings
+++ b/result/XPath/expr/strings
@@ -1,19 +1,76 @@
+
+========================
+Expression: string(5)
 Object is a string : 5
+
+========================
+Expression: string(0.5)
 Object is a string : 0.5
+
+========================
+Expression: string(-0.5)
 Object is a string : -0.5
+
+========================
+Expression: string(true())
 Object is a string : true
+
+========================
+Expression: string(false())
 Object is a string : false
+
+========================
+Expression: concat("titi","toto")
 Object is a string : tititoto
+
+========================
+Expression: concat("titi","toto","tata")
 Object is a string : tititototata
+
+========================
+Expression: starts-with("tititoto","titi")
 Object is a Boolean : true
+
+========================
+Expression: starts-with("tititoto","to")
 Object is a Boolean : false
+
+========================
+Expression: contains("tititototata","titi")
 Object is a Boolean : true
+
+========================
+Expression: contains("tititototata","toto")
 Object is a Boolean : true
+
+========================
+Expression: contains("tititototata","tata")
 Object is a Boolean : true
+
+========================
+Expression: contains("tititototata","tita")
 Object is a Boolean : false
+
+========================
+Expression: substring("12345",2,3)
 Object is a string : 234
+
+========================
+Expression: substring("12345",2)
 Object is a string : 2345
+
+========================
+Expression: substring("12345",1.5,2.6)
 Object is a string : 234
+
+========================
+Expression: substring("12345",0,3)
 Object is a string : 12
+
+========================
+Expression: string-length("")
 Object is a number : 0
+
+========================
+Expression: string-length("titi")
 Object is a number : 4
diff --git a/result/XPath/tests/chaptersbase b/result/XPath/tests/chaptersbase
index 1889535..4b5b9cc 100644
--- a/result/XPath/tests/chaptersbase
+++ b/result/XPath/tests/chaptersbase
@@ -1,24 +1,36 @@
+
+========================
+Expression: /child::EXAMPLE
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: /child::*
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: /child::EXAMPLE/child::head
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT head
+
+========================
+Expression: /child::EXAMPLE/child::*
 Object is a Node Set :
 Set contains 6 nodes:
 1    ELEMENT head
@@ -27,16 +39,28 @@
 4    ELEMENT chapter
 5    ELEMENT chapter
 6    ELEMENT chapter
+
+========================
+Expression: /child::EXAMPLE/child::head/child::title
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT title
+
+========================
+Expression: /child::EXAMPLE/child::head/child::title/child::text()
 Object is a Node Set :
 Set contains 1 nodes:
 1    TEXT
-    content=Welcome to Gnome
+      content=Welcome to Gnome
+
+========================
+Expression: /child::EXAMPLE/child::head/node()
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT title
+
+========================
+Expression: /descendant::title
 Object is a Node Set :
 Set contains 6 nodes:
 1    ELEMENT title
@@ -45,6 +69,9 @@
 4    ELEMENT title
 5    ELEMENT title
 6    ELEMENT title
+
+========================
+Expression: /descendant::p/ancestor::chapter
 Object is a Node Set :
 Set contains 5 nodes:
 1    ELEMENT chapter
diff --git a/result/XPath/tests/chaptersprefol b/result/XPath/tests/chaptersprefol
new file mode 100644
index 0000000..5c33f2d
--- /dev/null
+++ b/result/XPath/tests/chaptersprefol
@@ -0,0 +1,76 @@
+
+========================
+Expression: /following::*
+Object is a Node Set :
+Set contains 0 nodes:
+
+========================
+Expression: /preceding::*
+Object is a Node Set :
+Set contains 0 nodes:
+
+========================
+Expression: /child::EXAMPLE/preceding::*
+Object is a Node Set :
+Set contains 0 nodes:
+
+========================
+Expression: /child::EXAMPLE/following::*
+Object is a Node Set :
+Set contains 0 nodes:
+
+========================
+Expression: /child::EXAMPLE/child::chapter[3]/preceding::*
+Object is a Node Set :
+Set contains 10 nodes:
+1    ELEMENT p
+2    ELEMENT title
+3    ELEMENT chapter
+4    ELEMENT p
+5    ELEMENT image
+      ATTRIBUTE href
+        TEXT
+          content=linus.gif
+6    ELEMENT p
+7    ELEMENT title
+8    ELEMENT chapter
+9    ELEMENT title
+10    ELEMENT head
+
+========================
+Expression: /child::EXAMPLE/child::chapter[3]/following::*
+Object is a Node Set :
+Set contains 6 nodes:
+1    ELEMENT chapter
+2    ELEMENT title
+3    ELEMENT p
+4    ELEMENT chapter
+5    ELEMENT title
+6    ELEMENT p
+
+========================
+Expression: /child::EXAMPLE/child::chapter[1]/image/preceding::*
+Object is a Node Set :
+Set contains 4 nodes:
+1    ELEMENT p
+2    ELEMENT title
+3    ELEMENT title
+4    ELEMENT head
+
+========================
+Expression: /child::EXAMPLE/child::chapter[1]/image/following::*
+Object is a Node Set :
+Set contains 13 nodes:
+1    ELEMENT p
+2    ELEMENT chapter
+3    ELEMENT title
+4    ELEMENT p
+5    ELEMENT chapter
+6    ELEMENT title
+7    ELEMENT p
+8    ELEMENT chapter
+9    ELEMENT title
+10    ELEMENT p
+11    ELEMENT chapter
+12    ELEMENT title
+13    ELEMENT p
diff --git a/result/XPath/tests/idsimple b/result/XPath/tests/idsimple
index 3d2e9e2..3d15841 100644
--- a/result/XPath/tests/idsimple
+++ b/result/XPath/tests/idsimple
@@ -1,24 +1,33 @@
+
+========================
+Expression: //*[@id="root"]
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE id
         TEXT
-        content=root
+          content=root
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: //*[@id="chapter2"]
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT chapter
       ATTRIBUTE id
         TEXT
-        content=chapter2
+          content=chapter2
+
+========================
+Expression: //*[@id="chapter5"]
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT chapter
       ATTRIBUTE id
         TEXT
-        content=chapter5
+          content=chapter5
diff --git a/result/XPath/tests/simpleabbr b/result/XPath/tests/simpleabbr
index 9e3fcd3..188a719 100644
--- a/result/XPath/tests/simpleabbr
+++ b/result/XPath/tests/simpleabbr
@@ -1,39 +1,63 @@
+
+========================
+Expression: /EXAMPLE
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: /EXAMPLE/head
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT head
+
+========================
+Expression: /EXAMPLE/chapter[1]
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT chapter
+
+========================
+Expression: //p
 Object is a Node Set :
 Set contains 2 nodes:
 1    ELEMENT p
 2    ELEMENT p
+
+========================
+Expression: //chapter/image
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT image
       ATTRIBUTE href
         TEXT
-        content=linus.gif
+          content=linus.gif
+
+========================
+Expression: //p/text()
 Object is a Node Set :
 Set contains 2 nodes:
 1    TEXT
-    content=bla bla bla ...
+      content=bla bla bla ...
 2    TEXT
-    content=...
+      content=...
+
+========================
+Expression: //p/text()[position()=1]
 Object is a Node Set :
 Set contains 1 nodes:
 1    TEXT
-    content=bla bla bla ...
+      content=bla bla bla ...
+
+========================
+Expression: //p/text()[position()=last()]
 Object is a Node Set :
 Set contains 1 nodes:
 1    TEXT
-    content=...
+      content=...
diff --git a/result/XPath/tests/simplebase b/result/XPath/tests/simplebase
index db968d8..2e9687c 100644
--- a/result/XPath/tests/simplebase
+++ b/result/XPath/tests/simplebase
@@ -1,42 +1,69 @@
+
+========================
+Expression: /child::*
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: /child::EXAMPLE
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT EXAMPLE
       ATTRIBUTE prop1
         TEXT
-        content=gnome is great
+          content=gnome is great
       ATTRIBUTE prop2
         TEXT
-        content=& linux too
+          content=& linux too
+
+========================
+Expression: /child::EXAMPLE/child::head
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT head
+
+========================
+Expression: /child::EXAMPLE/child::*
 Object is a Node Set :
 Set contains 2 nodes:
 1    ELEMENT head
 2    ELEMENT chapter
+
+========================
+Expression: /child::EXAMPLE/child::head/child::title
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT title
+
+========================
+Expression: /child::EXAMPLE/child::head/child::title/child::text()
 Object is a Node Set :
 Set contains 1 nodes:
 1    TEXT
-    content=Welcome to Gnome
+      content=Welcome to Gnome
+
+========================
+Expression: /child::EXAMPLE/child::head/node()
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT title
+
+========================
+Expression: /descendant::title
 Object is a Node Set :
 Set contains 2 nodes:
 1    ELEMENT title
 2    ELEMENT title
+
+========================
+Expression: /descendant::p/ancestor::chapter
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT chapter
diff --git a/result/XPath/tests/usr1check b/result/XPath/tests/usr1check
index 989b79f..f1f2faa 100644
--- a/result/XPath/tests/usr1check
+++ b/result/XPath/tests/usr1check
@@ -1,9 +1,12 @@
+
+========================
+Expression: //ITEM[1]
 Object is a Node Set :
 Set contains 1 nodes:
 1    ELEMENT ITEM
       ATTRIBUTE monto
         TEXT
-        content=50.12
+          content=50.12
       ATTRIBUTE divisa
         TEXT
-        content=DOL
+          content=DOL
diff --git a/test/XPath/tests/chaptersprefol b/test/XPath/tests/chaptersprefol
new file mode 100644
index 0000000..e95995b
--- /dev/null
+++ b/test/XPath/tests/chaptersprefol
@@ -0,0 +1 @@
+/following::*                                                                   /preceding::*                                                                   /child::EXAMPLE/preceding::*                                                    /child::EXAMPLE/following::*                                                    /child::EXAMPLE/child::chapter[3]/preceding::*                                  /child::EXAMPLE/child::chapter[3]/following::*                                  /child::EXAMPLE/child::chapter[1]/image/preceding::*                            /child::EXAMPLE/child::chapter[1]/image/following::*
diff --git a/testXPath.c b/testXPath.c
index 49df1c4..d8c24ca 100644
--- a/testXPath.c
+++ b/testXPath.c
@@ -41,7 +41,10 @@
 #include <libxml/debugXML.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parserInternals.h>
-
+#if defined(LIBXML_XPTR_ENABLED)
+#include <libxml/xpointer.h>
+static int xptr = 0;
+#endif
 static int debug = 0;
 static int valid = 0;
 static int expr = 0;
@@ -138,11 +141,20 @@
     xmlXPathObjectPtr res;
     xmlXPathContextPtr ctxt;
     
-    ctxt = xmlXPathNewContext(document);
-    if (expr)
-	res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
-    else
-	res = xmlXPathEval(BAD_CAST str, ctxt);
+#if defined(LIBXML_XPTR_ENABLED)
+    if (xptr) {
+	ctxt = xmlXPtrNewContext(document, NULL, NULL);
+	res = xmlXPtrEval(BAD_CAST str, ctxt);
+    } else {
+#endif
+	ctxt = xmlXPathNewContext(document);
+	if (expr)
+	    res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
+	else
+	    res = xmlXPathEval(BAD_CAST str, ctxt);
+#if defined(LIBXML_XPTR_ENABLED)
+    }
+#endif
     xmlXPAthDebugDumpObject(stdout, res);
     xmlXPathFreeObject(res);
     xmlXPathFreeContext(ctxt);
@@ -158,6 +170,7 @@
 	return;
     }
     while (fscanf(input, "%s", expr) != EOF) {
+        printf("\n========================\nExpression: %s\n", expr) ;
         testXPath(expr);
     }
 
@@ -171,6 +184,10 @@
     char *filename = NULL;
 
     for (i = 1; i < argc ; i++) {
+#if defined(LIBXML_XPTR_ENABLED)
+	if ((!strcmp(argv[i], "-xptr")) || (!strcmp(argv[i], "--xptr")))
+	    xptr++;
+#endif
 	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
 	    debug++;
 	if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
diff --git a/xpath.c b/xpath.c
index 12ab43a..1ea8aea 100644
--- a/xpath.c
+++ b/xpath.c
@@ -1,7 +1,7 @@
 /*
  * 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.
+ *          designed to be used by both XSLT and XPtr.
  *
  * Reference: W3C Working Draft internal 5 July 1999
  *     http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html
@@ -49,6 +49,9 @@
 #include <libxml/valid.h>
 #include <libxml/xpath.h>
 #include <libxml/parserInternals.h>
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
 
 /* #define DEBUG */
 /* #define DEBUG_STEP */
@@ -792,6 +795,507 @@
     xmlFree(obj);
 }
 
+#ifdef LIBXML_XPTR_ENABLED
+/**
+ * xmlXPathNewPoint:
+ * @node:  the xmlNodePtr
+ * @index:  the index within the node
+ *
+ * Create a new xmlXPathObjectPtr of type point
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewPoint(xmlNodePtr node, int index) {
+    xmlXPathObjectPtr ret;
+
+    if (node == NULL)
+	return(NULL);
+    if (index < 0)
+	return(NULL);
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewPoint: out of memory\n");
+	return(NULL);
+    }
+    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    ret->type = XPATH_POINT;
+    ret->user = (void *) node;
+    ret->index = index;
+    return(ret);
+}
+
+/**
+ * xmlXPathNewRangePoints:
+ * @start:  the starting point
+ * @end:  the ending point
+ *
+ * Create a new xmlXPathObjectPtr of type range using 2 Points
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
+    xmlXPathObjectPtr ret;
+
+    if (start == NULL)
+	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) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangePoints: out of memory\n");
+	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;
+    return(ret);
+}
+
+/**
+ * xmlXPathNewRangePointNode:
+ * @start:  the starting point
+ * @end:  the ending node
+ *
+ * Create a new xmlXPathObjectPtr of type range from a point to a node
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
+    xmlXPathObjectPtr ret;
+
+    if (start == NULL)
+	return(NULL);
+    if (end == NULL)
+	return(NULL);
+    if (start->type != XPATH_POINT)
+	return(NULL);
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangePointNode: out of memory\n");
+	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;
+    return(ret);
+}
+
+/**
+ * xmlXPathNewRangeNodePoint:
+ * @start:  the starting node
+ * @end:  the ending point
+ *
+ * Create a new xmlXPathObjectPtr of type range from a node to a point
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
+    xmlXPathObjectPtr ret;
+
+    if (start == NULL)
+	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) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangeNodePoint: out of memory\n");
+	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;
+    return(ret);
+}
+
+/**
+ * xmlXPathNewRangeNodes:
+ * @start:  the starting node
+ * @end:  the ending node
+ *
+ * Create a new xmlXPathObjectPtr of type range using 2 nodes
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
+    xmlXPathObjectPtr ret;
+
+    if (start == NULL)
+	return(NULL);
+    if (end == NULL)
+	return(NULL);
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangeNodes: out of memory\n");
+	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;
+    return(ret);
+}
+
+/**
+ * xmlXPathNewRangeNodeObject:
+ * @start:  the starting node
+ * @end:  the ending object
+ *
+ * Create a new xmlXPathObjectPtr of type range from a not to an object
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+    xmlXPathObjectPtr ret;
+
+    if (start == NULL)
+	return(NULL);
+    if (end == NULL)
+	return(NULL);
+    switch (end->type) {
+	case XPATH_POINT:
+	    break;
+	case XPATH_NODESET:
+	    /*
+	     * Empty set ... 
+	     */
+	    if (end->nodesetval->nodeNr <= 0)
+		return(NULL);
+	    break;
+	default:
+	    TODO
+	    return(NULL);
+    }
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangeNodeObject: out of memory\n");
+	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;
+	case XPATH_NODESET: {
+	    ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - -1];
+	    ret->index2 = -1;
+	    break;
+	}
+	default:
+	    STRANGE
+	    return(NULL);
+    }
+    ret->user2 = end;
+    ret->index2 = -1;
+    return(ret);
+}
+
+#define XML_RANGESET_DEFAULT	10
+
+/**
+ * xmlXPathRangeSetCreate:
+ * @val:  an initial xmlXPathObjectPtr, or NULL
+ *
+ * Create a new xmlRangeSetPtr of type double and of value @val
+ *
+ * Returns the newly created object.
+ */
+xmlRangeSetPtr
+xmlXPathRangeSetCreate(xmlXPathObjectPtr val) {
+    xmlRangeSetPtr ret;
+
+    ret = (xmlRangeSetPtr) xmlMalloc(sizeof(xmlRangeSet));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangeSet: out of memory\n");
+	return(NULL);
+    }
+    memset(ret, 0 , (size_t) sizeof(xmlRangeSet));
+    if (val != NULL) {
+        ret->rangeTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
+					     sizeof(xmlXPathObjectPtr));
+	if (ret->rangeTab == NULL) {
+	    fprintf(xmlXPathDebug, "xmlXPathNewRangeSet: out of memory\n");
+	    return(NULL);
+	}
+	memset(ret->rangeTab, 0 ,
+	       XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
+        ret->rangeMax = XML_RANGESET_DEFAULT;
+	ret->rangeTab[ret->rangeNr++] = val;
+    }
+    return(ret);
+}
+
+/**
+ * xmlXPathRangeSetAdd:
+ * @cur:  the initial range set
+ * @val:  a new xmlXPathObjectPtr
+ *
+ * add a new xmlXPathObjectPtr ot an existing RangeSet
+ */
+void
+xmlXPathRangeSetAdd(xmlRangeSetPtr cur, xmlXPathObjectPtr val) {
+    int i;
+
+    if (val == NULL) return;
+
+    /*
+     * check against doublons
+     */
+    for (i = 0;i < cur->rangeNr;i++)
+        if (cur->rangeTab[i] == val) return;
+
+    /*
+     * grow the rangeTab if needed
+     */
+    if (cur->rangeMax == 0) {
+        cur->rangeTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
+					     sizeof(xmlXPathObjectPtr));
+	if (cur->rangeTab == NULL) {
+	    fprintf(xmlXPathDebug, "xmlXPathRangeSetAdd: out of memory\n");
+	    return;
+	}
+	memset(cur->rangeTab, 0 ,
+	       XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
+        cur->rangeMax = XML_RANGESET_DEFAULT;
+    } else if (cur->rangeNr == cur->rangeMax) {
+        xmlXPathObjectPtr *temp;
+
+        cur->rangeMax *= 2;
+	temp = (xmlXPathObjectPtr *) xmlRealloc(cur->rangeTab, cur->rangeMax *
+				      sizeof(xmlXPathObjectPtr));
+	if (temp == NULL) {
+	    fprintf(xmlXPathDebug, "xmlXPathRangeSetAdd: out of memory\n");
+	    return;
+	}
+	cur->rangeTab = temp;
+    }
+    cur->rangeTab[cur->rangeNr++] = val;
+}
+
+/**
+ * xmlXPathRangeSetMerge:
+ * @val1:  the first RangeSet
+ * @val2:  the second RangeSet
+ *
+ * Merges two rangesets, all ranges from @val2 are added to @val1
+ *
+ * Returns val1 once extended or NULL in case of error.
+ */
+xmlRangeSetPtr
+xmlXPathRangeSetMerge(xmlRangeSetPtr val1, xmlRangeSetPtr val2) {
+    int i;
+
+    if (val1 == NULL) return(NULL);
+    if (val2 == NULL) return(val1);
+
+    /*
+     * !!!!! this can be optimized a lot, knowing that both
+     *       val1 and val2 already have unicity of their values.
+     */
+
+    for (i = 0;i < val2->rangeNr;i++)
+        xmlXPathRangeSetAdd(val1, val2->rangeTab[i]);
+
+    return(val1);
+}
+
+/**
+ * xmlXPathRangeSetDel:
+ * @cur:  the initial range set
+ * @val:  an xmlXPathObjectPtr
+ *
+ * Removes an xmlXPathObjectPtr from an existing RangeSet
+ */
+void
+xmlXPathRangeSetDel(xmlRangeSetPtr cur, xmlXPathObjectPtr val) {
+    int i;
+
+    if (cur == NULL) return;
+    if (val == NULL) return;
+
+    /*
+     * check against doublons
+     */
+    for (i = 0;i < cur->rangeNr;i++)
+        if (cur->rangeTab[i] == val) break;
+
+    if (i >= cur->rangeNr) {
+#ifdef DEBUG
+        fprintf(xmlXPathDebug, 
+	        "xmlXPathRangeSetDel: Range %s wasn't found in RangeList\n",
+		val->name);
+#endif
+        return;
+    }
+    cur->rangeNr--;
+    for (;i < cur->rangeNr;i++)
+        cur->rangeTab[i] = cur->rangeTab[i + 1];
+    cur->rangeTab[cur->rangeNr] = NULL;
+}
+
+/**
+ * xmlXPathRangeSetRemove:
+ * @cur:  the initial range set
+ * @val:  the index to remove
+ *
+ * Removes an entry from an existing RangeSet list.
+ */
+void
+xmlXPathRangeSetRemove(xmlRangeSetPtr cur, int val) {
+    if (cur == NULL) return;
+    if (val >= cur->rangeNr) return;
+    cur->rangeNr--;
+    for (;val < cur->rangeNr;val++)
+        cur->rangeTab[val] = cur->rangeTab[val + 1];
+    cur->rangeTab[cur->rangeNr] = NULL;
+}
+
+/**
+ * xmlXPathFreeRangeSet:
+ * @obj:  the xmlRangeSetPtr to free
+ *
+ * Free the RangeSet compound (not the actual ranges !).
+ */
+void
+xmlXPathFreeRangeSet(xmlRangeSetPtr obj) {
+    if (obj == NULL) return;
+    if (obj->rangeTab != NULL) {
+#ifdef DEBUG
+	memset(obj->rangeTab, 0xB ,
+	       (size_t) sizeof(xmlXPathObjectPtr) * obj->rangeMax);
+#endif
+	xmlFree(obj->rangeTab);
+    }
+#ifdef DEBUG
+    memset(obj, 0xB , (size_t) sizeof(xmlRangeSet));
+#endif
+    xmlFree(obj);
+}
+
+#if defined(DEBUG) || defined(DEBUG_STEP)
+/**
+ * xmlXPathDebugRangeSet:
+ * @output:  a FILE * for the output
+ * @obj:  the xmlRangeSetPtr to free
+ *
+ * Quick display of a RangeSet
+ */
+void
+xmlXPathDebugRangeSet(FILE *output, xmlRangeSetPtr obj) {
+    int i;
+
+    if (output == NULL) output = xmlXPathDebug;
+    if (obj == NULL)  {
+        fprintf(output, "RangeSet == NULL !\n");
+	return;
+    }
+    if (obj->rangeNr == 0) {
+        fprintf(output, "RangeSet is empty\n");
+	return;
+    }
+    if (obj->rangeTab == NULL) {
+	fprintf(output, " rangeTab == NULL !\n");
+	return;
+    }
+    for (i = 0; i < obj->rangeNr; i++) {
+        if (obj->rangeTab[i] == NULL) {
+	    fprintf(output, " NULL !\n");
+	    return;
+        }
+	if ((obj->rangeTab[i]->type == XML_DOCUMENT_NODE) ||
+	    (obj->rangeTab[i]->type == XML_HTML_DOCUMENT_NODE))
+	    fprintf(output, " /");
+	else if (obj->rangeTab[i]->name == NULL)
+	    fprintf(output, " noname!");
+	else fprintf(output, " %s", obj->rangeTab[i]->name);
+    }
+    fprintf(output, "\n");
+}
+#endif
+
+/**
+ * xmlXPathNewRangeSetNodes:
+ * @start:  the NodePtr value
+ * @end:  the NodePtr value
+ *
+ * Create a new xmlXPathObjectPtr of type RangeSet and initialize
+ * it with the single range made of the two nodes @start and @end
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathNewRangeSetNodes(xmlNodePtr start, xmlNodePtr end) {
+    xmlXPathObjectPtr ret;
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathNewRangeSet: out of memory\n");
+	return(NULL);
+    }
+    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    ret->type = XPATH_LOCATIONSET;
+    ret->user = xmlXPathRangeSetCreate(xmlXPathNewRangeNodes(start, end));
+    return(ret);
+}
+
+/**
+ * xmlXPathWrapRangeSet:
+ * @val:  the RangeSet value
+ *
+ * Wrap the RangeSet @val in a new xmlXPathObjectPtr
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathWrapRangeSet(xmlRangeSetPtr val) {
+    xmlXPathObjectPtr ret;
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathWrapRangeSet: out of memory\n");
+	return(NULL);
+    }
+    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    ret->type = XPATH_LOCATIONSET;
+    ret->user = (void *) val;
+    return(ret);
+}
+
+#endif /* LIBXML_XPTR_ENABLED */
+
 /**
  * xmlXPathFreeObject:
  * @obj:  the object to free
@@ -801,10 +1305,14 @@
 void
 xmlXPathFreeObject(xmlXPathObjectPtr obj) {
     if (obj == NULL) return;
-    if (obj->nodesetval != NULL)
-        xmlXPathFreeNodeSet(obj->nodesetval);
-    if (obj->stringval != NULL)
-        xmlFree(obj->stringval);
+    if (obj->type == XPATH_NODESET) {
+	if (obj->nodesetval != NULL)
+	    xmlXPathFreeNodeSet(obj->nodesetval);
+    } else if (obj->type == XPATH_STRING) {
+	if (obj->stringval != NULL)
+	    xmlFree(obj->stringval);
+    }
+
 #ifdef DEBUG
     memset(obj, 0xB , (size_t) sizeof(xmlXPathObject));
 #endif
@@ -1153,6 +1661,9 @@
 		    ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval);
 		    break;
 		case XPATH_USERS:
+		case XPATH_POINT:
+		case XPATH_RANGE:
+		case XPATH_LOCATIONSET:
 		    TODO
 		    break;
 	    }
@@ -1190,6 +1701,9 @@
 		    ret = (arg1->boolval == ret);
 		    break;
 		case XPATH_USERS:
+		case XPATH_POINT:
+		case XPATH_RANGE:
+		case XPATH_LOCATIONSET:
 		    TODO
 		    break;
 	    }
@@ -1218,6 +1732,9 @@
 		    ret = (arg1->floatval == arg2->floatval);
 		    break;
 		case XPATH_USERS:
+		case XPATH_POINT:
+		case XPATH_RANGE:
+		case XPATH_LOCATIONSET:
 		    TODO
 		    break;
 	    }
@@ -1249,11 +1766,17 @@
 		    ret = (arg1->floatval == arg2->floatval);
 		    break;
 		case XPATH_USERS:
+		case XPATH_POINT:
+		case XPATH_RANGE:
+		case XPATH_LOCATIONSET:
 		    TODO
 		    break;
 	    }
 	    break;
         case XPATH_USERS:
+	case XPATH_POINT:
+	case XPATH_RANGE:
+	case XPATH_LOCATIONSET:
 	    TODO
 	    break;
     }
@@ -1852,25 +2375,29 @@
 xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
     if (cur != NULL && cur->children != NULL)
         return cur->children ;
-    if (cur == NULL)
-        if ((cur = ctxt->context->node) == NULL) return(NULL) ;
+    if (cur == NULL) cur = ctxt->context->node;
+    if (cur == NULL) return(NULL) ; /* ERROR */
+    if (cur->next != NULL) return(cur->next) ;
     do {
         cur = cur->parent;
         if (cur == NULL) return(NULL);
-        if (cur == ctxt->context->doc->children) return(NULL);
-        if (cur->next != NULL) {
-            cur = cur->next;
-            return(cur);
-        }
+        if (cur == ctxt->context->doc->children) return(NULL); /* !!!!!?!? */
+        if (cur->next != NULL) return(cur->next);
     } while (cur != NULL);
     return(cur);
 }
 
 /*
+ * xmlXPathIsAncestor:
+ * @ancestor:  the ancestor node
+ * @node:  the current node
+ *
+ * Check that @ancestor is a @node's ancestor
+ *
  * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
  */
 static int
-isAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
+xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
     xmlNodePtr tmp ;
     if (ancestor == NULL || node == NULL) return 0 ;
     for (tmp = node ; tmp->parent != NULL ; tmp = tmp->parent) {
@@ -1907,81 +2434,10 @@
         cur = cur->parent;
         if (cur == NULL) return(NULL);
         if (cur == ctxt->context->doc->children) return(NULL);
-    } while (isAncestor(cur, ctxt->context->node));
+    } while (xmlXPathIsAncestor(cur, ctxt->context->node));
     return(cur);
 }
 
-#if 0
-/* OLD VERSION, I was told they were broken ! */
-/**
- * xmlXPathNextFollowing:
- * @ctxt:  the XPath Parser context
- * @cur:  the current node in the traversal
- *
- * Traversal function for the "following" direction
- * The following axis contains all nodes in the same document as the context
- * node that are after the context node in document order, excluding any
- * descendants and excluding attribute nodes and namespace nodes; the nodes
- * are ordered in document order
- *
- * Returns the next element following that axis
- */
-xmlNodePtr
-xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if (cur == (xmlNodePtr) ctxt->context->doc)
-        return(NULL);
-    if (cur == NULL)
-        return(ctxt->context->node->next);; /* !!!!!!!!! */
-    if (cur->children != NULL) return(cur->children);
-    if (cur->next != NULL) return(cur->next);
-    
-    do {
-        cur = cur->parent;
-	if (cur == NULL) return(NULL);
-	if (cur == ctxt->context->doc->children) return(NULL);
-	if (cur->next != NULL) {
-	    cur = cur->next;
-	    return(cur);
-	}
-    } while (cur != NULL);
-    return(cur);
-}
-
-/**
- * xmlXPathNextPreceding:
- * @ctxt:  the XPath Parser context
- * @cur:  the current node in the traversal
- *
- * Traversal function for the "preceding" direction
- * the preceding axis contains all nodes in the same document as the context
- * node that are before the context node in document order, excluding any
- * ancestors and excluding attribute nodes and namespace nodes; the nodes are
- * ordered in reverse document order
- *
- * Returns the next element following that axis
- */
-xmlNodePtr
-xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
-    if (cur == (xmlNodePtr) ctxt->context->doc)
-        return(NULL);
-    if (cur == NULL)
-        return(ctxt->context->node->prev); /* !!!!!!!!! */
-    if (cur->last != NULL) return(cur->last);
-    if (cur->prev != NULL) return(cur->prev);
-    
-    do {
-        cur = cur->parent;
-	if (cur == NULL) return(NULL);
-	if (cur == ctxt->context->doc->children) return(NULL);
-	if (cur->prev != NULL) {
-	    cur = cur->prev;
-	    return(cur);
-	}
-    } while (cur != NULL);
-    return(cur);
-}
-#endif
-
 /**
  * xmlXPathNextNamespace:
  * @ctxt:  the XPath Parser context
@@ -2653,6 +3109,9 @@
 	    return;
 	}
 	case XPATH_USERS:
+	case XPATH_POINT:
+	case XPATH_RANGE:
+	case XPATH_LOCATIONSET:
 	    TODO
 	    valuePush(ctxt, xmlXPathNewCString(""));
 	    break;
@@ -3242,6 +3701,9 @@
 	    valuePush(ctxt, cur);
 	    return;
 	case XPATH_USERS:
+	case XPATH_POINT:
+	case XPATH_RANGE:
+	case XPATH_LOCATIONSET:
 	    TODO
 	    valuePush(ctxt, xmlXPathNewFloat(0.0));
 	    break;
@@ -4675,10 +5137,17 @@
  * xmlXPathEvalStep:
  * @ctxt:  the XPath Parser context
  *
- *  [4]   Step ::=   Basis Predicate*
+ *  TODO [4] was changed between the WD and the REC
+ *
+ *  [4]   Step ::=   AxisSpecifier NodeTest Predicate*
  *                     | AbbreviatedStep 
- *  [12]   AbbreviatedStep ::=   '.'
- *                           | '..'
+ *  [12]   AbbreviatedStep ::=   '.' | '..'
+ *
+ * Modified for XPtr range support as:
+ *
+ *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
+ *                     | AbbreviatedStep
+ *                     | 'range-to' '(' Expr ')' Predicate*
  *
  * Evaluate one step in a Location Path
  * A location step of . is short for self::node(). This is
@@ -4704,7 +5173,99 @@
 	NEXT;
 	SKIP_BLANKS;
     } else {
-	xmlXPathEvalBasis(ctxt);
+#ifdef LIBXML_XPTR_ENABLED
+	if ((CUR == 'r') && (NXT(1) == 'a') && (NXT(2) == 'n') &&
+	    (NXT(3) == 'g') && (NXT(4) == 'e') && (NXT(5) == '-') &&
+	    (NXT(6) == 't') && (NXT(7) == 'o')) {
+	    xmlXPathObjectPtr range;
+	    const xmlChar *cur;
+	    xmlXPathObjectPtr res, obj;
+	    xmlXPathObjectPtr tmp;
+	    xmlRangeSetPtr newset = NULL;
+	    xmlNodeSetPtr oldset;
+	    int i;
+
+	    CHECK_TYPE(XPATH_NODESET);
+	    obj = valuePop(ctxt);
+	    oldset = obj->nodesetval;
+	    ctxt->context->node = NULL;
+
+	    SKIP(8);
+	    SKIP_BLANKS;
+	    if (CUR != '(') {
+		XP_ERROR(XPATH_EXPR_ERROR);
+	    }
+	    NEXT;
+	    SKIP_BLANKS;
+
+	    /*
+	     * Save the expression pointer since we will have to evaluate
+	     * it multiple times. Initialize the new set.
+	     */
+	    cur = ctxt->cur;
+	    newset = xmlXPathRangeSetCreate(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 = xmlXPathNewRangeNodeObject(oldset->nodeTab[0], res);
+		if (range != NULL) {
+		    xmlXPathRangeSetAdd(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, xmlXPathWrapRangeSet(newset));
+
+	    SKIP_BLANKS;
+	    if (CUR != ')') {
+		XP_ERROR(XPATH_EXPR_ERROR);
+	    }
+	    NEXT;
+	    SKIP_BLANKS;
+	} else
+#endif
+	{
+	    /*
+	     * TODO cleanup productions/procedures
+	     * Basis is no more an XPath production !
+	     */
+	    xmlXPathEvalBasis(ctxt);
+	}
 	SKIP_BLANKS;
 	while (CUR == '[') {
 	    xmlXPathEvalPredicate(ctxt);
@@ -4854,6 +5415,63 @@
 }
 
 /**
+ * xmlXPathEvalXPtrExpr:
+ * @str:  the XPointer XPtrExpr expression
+ * @ctx:  the XPointer context
+ *
+ * Evaluate the location set corresponding to this expression.
+ *
+ * Returns the xmlXPathObjectPtr resulting from the eveluation or NULL.
+ *         the caller has to free the object.
+ */
+xmlXPathObjectPtr
+xmlXPathEvalXPtrExpr(const xmlChar *str, xmlXPathContextPtr ctx) {
+    xmlXPathParserContextPtr ctxt;
+    xmlXPathObjectPtr res = NULL, tmp;
+    int stack = 0;
+
+    xmlXPathInit();
+
+    CHECK_CONTEXT(ctx)
+
+    if (xmlXPathDebug == NULL)
+        xmlXPathDebug = stderr;
+    ctxt = xmlXPathNewParserContext(str, ctx);
+    valuePush(ctxt, xmlXPathNewNodeSet(ctx->node));
+    if (str[0] == '/')
+        xmlXPathRoot(ctxt);
+    xmlXPathEvalExpr(ctxt);
+
+    if ((ctxt->value == NULL) ||
+	((ctxt->value->type != XPATH_NODESET) &&
+	 (ctxt->value->type != XPATH_LOCATIONSET))) {
+	fprintf(xmlXPathDebug,
+		"xmlXPathEval: evaluation failed to return a node set\n");
+    } else {
+	res = valuePop(ctxt);
+    }
+
+    do {
+        tmp = valuePop(ctxt);
+	if (tmp != NULL) {
+	    xmlXPathFreeObject(tmp);
+	    stack++;    
+        }
+    } while (tmp != NULL);
+    if (stack != 0) {
+	fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n",
+	        stack);
+    }
+    if (ctxt->error != XPATH_EXPRESSION_OK) {
+	xmlXPathFreeObject(res);
+	res = NULL;
+    }
+        
+    xmlXPathFreeParserContext(ctxt);
+    return(res);
+}
+
+/**
  * xmlXPathEvalExpression:
  * @str:  the XPath expression
  * @ctxt:  the XPath context
diff --git a/xpath.h b/xpath.h
index 6c5f42e..631f59f 100644
--- a/xpath.h
+++ b/xpath.h
@@ -51,7 +51,10 @@
     XPATH_BOOLEAN = 2,
     XPATH_NUMBER = 3,
     XPATH_STRING = 4,
-    XPATH_USERS = 5
+    XPATH_POINT = 5,
+    XPATH_RANGE = 6,
+    XPATH_LOCATIONSET = 7,
+    XPATH_USERS = 8
 } xmlXPathObjectType;
 
 typedef struct _xmlXPathObject xmlXPathObject;
@@ -63,6 +66,9 @@
     double floatval;
     xmlChar *stringval;
     void *user;
+    int index;
+    void *user2;
+    int index2;
 };
 
 /*
@@ -168,6 +174,11 @@
     /* extra variables */
     int contextSize;			/* the context size */
     int proximityPosition;		/* the proximity position */
+
+    /* extra stuff for XPointer */
+    int xptr;				/* it this an XPointer context */
+    xmlNodePtr here;			/* for here() */
+    xmlNodePtr origin;			/* for origin() */
 };
 
 /*
@@ -220,10 +231,13 @@
 /**
  * Evaluation functions.
  */
+void		   xmlXPathInit			(void);
 xmlXPathContextPtr xmlXPathNewContext		(xmlDocPtr doc);
 void		   xmlXPathFreeContext		(xmlXPathContextPtr ctxt);
 xmlXPathObjectPtr  xmlXPathEval			(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);
+xmlXPathObjectPtr  xmlXPathEvalXPtrExpr		(const xmlChar *str,
+						 xmlXPathContextPtr ctxt);
 void		   xmlXPathFreeObject		(xmlXPathObjectPtr obj);
 xmlXPathObjectPtr  xmlXPathEvalExpression	(const xmlChar *str,
 						 xmlXPathContextPtr ctxt);