Big XPath cleanup continues, one URI fix:
- xpath.[ch] debugXML.c testXPath.c: fixed the XPath evaluation
  engine, should be far more stable, incorporated a new version of
  preceding/following axis, need testing
- uri.c: fixed file:///c:/a/b/c problem
- test/XPath/tests/idsimple: augmented the XPath tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index fb205e6..655832b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Mon Oct  2 23:47:32 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* xpath.[ch] debugXML.c testXPath.c: fixed the XPath evaluation
+	  engine, should be far more stable, incorporated a new version of
+	  preceding/following axis, need testing
+        * uri.c: fixed file:///c:/a/b/c problem
+	* test/XPath/tests/idsimple: augmented the XPath tests
+
 Sun Oct  1 22:33:00 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
 
 	* doc/* rebuilding docs for 2.2.4 release
diff --git a/debugXML.c b/debugXML.c
index 36e1c3c..0363352 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -1649,9 +1649,7 @@
 	    } else {
 	        ctxt->pctxt->node = ctxt->node;
 #ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-	        ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
+	        ctxt->pctxt->node = ctxt->node;
 		list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 #else
 		list = NULL;
@@ -1688,21 +1686,14 @@
 		} else {
 		    fprintf(stderr, "%s: no such node\n", arg);
 		}
-#ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-#endif /* LIBXML_XPATH_ENABLED */
-		ctxt->pctxt->nodelist = NULL;
+		ctxt->pctxt->node = NULL;
 	    }
 	} else if (!strcmp(command, "cd")) {
 	    if (arg[0] == 0) {
 		ctxt->node = (xmlNodePtr) ctxt->doc;
 	    } else {
-	        ctxt->pctxt->node = ctxt->node;
 #ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-	        ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
+	        ctxt->pctxt->node = ctxt->node;
 		list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 #else
 		list = NULL;
@@ -1733,11 +1724,7 @@
 		} else {
 		    fprintf(stderr, "%s: no such node\n", arg);
 		}
-#ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-#endif /* LIBXML_XPATH_ENABLED */
-		ctxt->pctxt->nodelist = NULL;
+		ctxt->pctxt->node = NULL;
 	    }
 	} else if (!strcmp(command, "cat")) {
 	    if (arg[0] == 0) {
@@ -1745,9 +1732,7 @@
 	    } else {
 	        ctxt->pctxt->node = ctxt->node;
 #ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-	        ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
+	        ctxt->pctxt->node = ctxt->node;
 		list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
 #else
 		list = NULL;
@@ -1781,11 +1766,7 @@
 		} else {
 		    fprintf(stderr, "%s: no such node\n", arg);
 		}
-#ifdef LIBXML_XPATH_ENABLED
-		if (ctxt->pctxt->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
-#endif /* LIBXML_XPATH_ENABLED */
-		ctxt->pctxt->nodelist = NULL;
+		ctxt->pctxt->node = NULL;
 	    }
 	} else {
 	    fprintf(stderr, "Unknown command %s\n", command);
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 0efe466..6c5f42e 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -143,7 +143,6 @@
 struct _xmlXPathContext {
     xmlDocPtr doc;			/* The current document */
     xmlNodePtr node;			/* The current node */
-    xmlNodeSetPtr nodelist;		/* The current node list */
 
     int nb_variables;			/* number of defined variables */
     int max_variables;			/* max number of variables */
diff --git a/result/XPath/tests/idsimple b/result/XPath/tests/idsimple
new file mode 100644
index 0000000..3d2e9e2
--- /dev/null
+++ b/result/XPath/tests/idsimple
@@ -0,0 +1,24 @@
+Object is a Node Set :
+Set contains 1 nodes:
+1    ELEMENT EXAMPLE
+      ATTRIBUTE id
+        TEXT
+        content=root
+      ATTRIBUTE prop1
+        TEXT
+        content=gnome is great
+      ATTRIBUTE prop2
+        TEXT
+        content=& linux too
+Object is a Node Set :
+Set contains 1 nodes:
+1    ELEMENT chapter
+      ATTRIBUTE id
+        TEXT
+        content=chapter2
+Object is a Node Set :
+Set contains 1 nodes:
+1    ELEMENT chapter
+      ATTRIBUTE id
+        TEXT
+        content=chapter5
diff --git a/test/XPath/tests/idsimple b/test/XPath/tests/idsimple
new file mode 100644
index 0000000..2841ae9
--- /dev/null
+++ b/test/XPath/tests/idsimple
@@ -0,0 +1,3 @@
+//*[@id="root"]
+//*[@id="chapter2"]
+//*[@id="chapter5"]
diff --git a/testXPath.c b/testXPath.c
index 1559cef..49df1c4 100644
--- a/testXPath.c
+++ b/testXPath.c
@@ -40,8 +40,10 @@
 #include <libxml/parser.h>
 #include <libxml/debugXML.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/parserInternals.h>
 
 static int debug = 0;
+static int valid = 0;
 static int expr = 0;
 static xmlDocPtr document = NULL;
 
@@ -171,6 +173,8 @@
     for (i = 1; i < argc ; i++) {
 	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
 	    debug++;
+	if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
+	    valid++;
 	if ((!strcmp(argv[i], "-expr")) || (!strcmp(argv[i], "--expr")))
 	    expr++;
 	if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input")))
@@ -178,6 +182,7 @@
 	if ((!strcmp(argv[i], "-f")) || (!strcmp(argv[i], "--file")))
 	    usefile++;
     }
+    if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
     if (document == NULL) {
         if (filename == NULL)
 	    document = xmlParseDoc(buffer);
@@ -201,6 +206,7 @@
 	       argv[0]);
 	printf("\tParse the XPath strings and output the result of the parsing\n");
 	printf("\t--debug : dump a debug version of the result\n");
+	printf("\t--valid : switch on DTD support in the parser\n");
 	printf("\t--expr : debug XPath expressions only\n");
 	printf("\t--input filename : or\n");
 	printf("\t-i filename      : read the document from filename\n");
diff --git a/uri.c b/uri.c
index 7166c5d..cb1c215 100644
--- a/uri.c
+++ b/uri.c
@@ -373,6 +373,17 @@
 		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
 		}
 	    }
+	} else if (uri->scheme != NULL) {
+	    if (len + 3 >= max) {
+		max *= 2;
+		ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
+		if (ret == NULL) {
+		    fprintf(stderr, "xmlSaveUri: out of memory\n");
+		    return(NULL);
+		}
+	    }
+	    ret[len++] = '/';
+	    ret[len++] = '/';
 	}
 	if (uri->path != NULL) {
 	    p = uri->path;
@@ -767,11 +778,24 @@
         cur = *str;
     }
     /*
+     * This can be empty in the case where there is no server
+     */
+    host = cur;
+    if (*cur == '/') {
+	if (uri != NULL) {
+	    if (uri->authority != NULL) xmlFree(uri->authority);
+	    uri->authority = NULL;
+	    if (uri->server != NULL) xmlFree(uri->server);
+	    uri->server = NULL;
+	    uri->port = 0;
+	}
+	return(0);
+    }
+    /*
      * host part of hostport can derive either an IPV4 address
      * or an unresolved name. Check the IP first, it easier to detect
      * errors if wrong one
      */
-    host = cur;
     if (IS_DIGIT(*cur)) {
         while(IS_DIGIT(*cur)) cur++;
 	if (*cur != '.')
diff --git a/xpath.c b/xpath.c
index 093866e..12ab43a 100644
--- a/xpath.c
+++ b/xpath.c
@@ -646,7 +646,7 @@
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n");
+        fprintf(xmlXPathDebug, "xmlXPathNewBoolean: out of memory\n");
 	return(NULL);
     }
     memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@@ -669,7 +669,7 @@
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n");
+        fprintf(xmlXPathDebug, "xmlXPathNewString: out of memory\n");
 	return(NULL);
     }
     memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@@ -692,7 +692,7 @@
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n");
+        fprintf(xmlXPathDebug, "xmlXPathNewCString: out of memory\n");
 	return(NULL);
     }
     memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@@ -716,7 +716,7 @@
 
     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
     if (ret == NULL) {
-        fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n");
+        fprintf(xmlXPathDebug, "xmlXPathNewNodeSet: out of memory\n");
 	return(NULL);
     }
     memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@@ -754,6 +754,29 @@
 }
 
 /**
+ * xmlXPathWrapNodeSet:
+ * @val:  the NodePtr value
+ *
+ * Wrap the Nodeset @val in a new xmlXPathObjectPtr
+ *
+ * Returns the newly created object.
+ */
+xmlXPathObjectPtr
+xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
+    xmlXPathObjectPtr ret;
+
+    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+    if (ret == NULL) {
+        fprintf(xmlXPathDebug, "xmlXPathWrapNodeSet: out of memory\n");
+	return(NULL);
+    }
+    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
+    ret->type = XPATH_NODESET;
+    ret->nodesetval = val;
+    return(ret);
+}
+
+/**
  * xmlXPathFreeNodeSetList:
  * @obj:  an existing NodeSetList object
  *
@@ -813,12 +836,7 @@
     }
     memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
     ret->doc = doc;
- /***********   
-    ret->node = (xmlNodePtr) doc;
-    ret->nodelist = xmlXPathNodeSetCreate(ret->node);
-  ***********/  
     ret->node = NULL;
-    ret->nodelist = NULL;
 
     ret->nb_variables = 0;
     ret->max_variables = 0;
@@ -856,8 +874,6 @@
     if (ctxt->namespaces != NULL)
         xmlFree(ctxt->namespaces);
 
-    if (ctxt->nodelist != NULL) 
-        xmlXPathFreeNodeSet(ctxt->nodelist);
 #ifdef DEBUG
     memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext));
 #endif
@@ -870,14 +886,14 @@
  *									*
  ************************************************************************/
 
-#define CHECK_CTXT							\
+#define CHECK_CTXT(ctxt)						\
     if (ctxt == NULL) { 						\
         fprintf(xmlXPathDebug, "%s:%d Internal error: ctxt == NULL\n",	\
 	        __FILE__, __LINE__);					\
     }									\
 
 
-#define CHECK_CONTEXT							\
+#define CHECK_CONTEXT(ctxt)						\
     if (ctxt == NULL) { 						\
         fprintf(xmlXPathDebug, "%s:%d Internal error: no context\n",	\
 	        __FILE__, __LINE__);					\
@@ -1136,6 +1152,9 @@
 		case XPATH_STRING:
 		    ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval);
 		    break;
+		case XPATH_USERS:
+		    TODO
+		    break;
 	    }
 	    break;
         case XPATH_BOOLEAN:
@@ -1170,6 +1189,9 @@
 			ret = 1;
 		    ret = (arg1->boolval == ret);
 		    break;
+		case XPATH_USERS:
+		    TODO
+		    break;
 	    }
 	    break;
         case XPATH_NUMBER:
@@ -1195,6 +1217,9 @@
 		case XPATH_NUMBER:
 		    ret = (arg1->floatval == arg2->floatval);
 		    break;
+		case XPATH_USERS:
+		    TODO
+		    break;
 	    }
 	    break;
         case XPATH_STRING:
@@ -1223,8 +1248,14 @@
 		    arg1 = valuePop(ctxt);
 		    ret = (arg1->floatval == arg2->floatval);
 		    break;
+		case XPATH_USERS:
+		    TODO
+		    break;
 	    }
 	    break;
+        case XPATH_USERS:
+	    TODO
+	    break;
     }
     xmlXPathFreeObject(arg1);
     xmlXPathFreeObject(arg2);
@@ -1443,19 +1474,21 @@
  *									*
  ************************************************************************/
 
-#define AXIS_ANCESTOR			1
-#define AXIS_ANCESTOR_OR_SELF		2
-#define AXIS_ATTRIBUTE			3
-#define AXIS_CHILD			4
-#define AXIS_DESCENDANT			5
-#define AXIS_DESCENDANT_OR_SELF		6
-#define AXIS_FOLLOWING			7
-#define AXIS_FOLLOWING_SIBLING		8
-#define AXIS_NAMESPACE			9
-#define AXIS_PARENT			10
-#define AXIS_PRECEDING			11
-#define AXIS_PRECEDING_SIBLING		12
-#define AXIS_SELF			13
+typedef enum {
+    AXIS_ANCESTOR = 1,
+    AXIS_ANCESTOR_OR_SELF,
+    AXIS_ATTRIBUTE,
+    AXIS_CHILD,
+    AXIS_DESCENDANT,
+    AXIS_DESCENDANT_OR_SELF,
+    AXIS_FOLLOWING,
+    AXIS_FOLLOWING_SIBLING,
+    AXIS_NAMESPACE,
+    AXIS_PARENT,
+    AXIS_PRECEDING,
+    AXIS_PRECEDING_SIBLING,
+    AXIS_SELF
+} xmlXPathAxisVal;
 
 /*
  * A traversal function enumerates nodes along an axis.
@@ -1817,6 +1850,84 @@
  */
 xmlNodePtr
 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) ;
+    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);
+}
+
+/*
+ * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
+ */
+static int
+isAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
+    xmlNodePtr tmp ;
+    if (ancestor == NULL || node == NULL) return 0 ;
+    for (tmp = node ; tmp->parent != NULL ; tmp = tmp->parent) {
+        if (tmp->parent == ancestor)
+            return 1 ;
+    }
+    return 0 ;
+}
+
+/**
+ * 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 == NULL)
+        cur = ctxt->context->node ;
+    do {
+        if (cur->prev != NULL) {
+            for (cur = cur->prev ; cur->last != NULL ; cur = cur->last)
+                ;
+            return(cur) ;
+        }
+
+        cur = cur->parent;
+        if (cur == NULL) return(NULL);
+        if (cur == ctxt->context->doc->children) return(NULL);
+    } while (isAncestor(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)
@@ -1869,6 +1980,7 @@
     } while (cur != NULL);
     return(cur);
 }
+#endif
 
 /**
  * xmlXPathNextNamespace:
@@ -1921,24 +2033,32 @@
  *									*
  ************************************************************************/
 
-#define NODE_TEST_NONE	0
-#define NODE_TEST_TYPE	1
-#define NODE_TEST_PI	2
-#define NODE_TEST_ALL	3
-#define NODE_TEST_NS	4
-#define NODE_TEST_NAME	5
+typedef enum {
+    NODE_TEST_NONE = 0,
+    NODE_TEST_TYPE = 1,
+    NODE_TEST_PI = 2,
+    NODE_TEST_ALL = 3,
+    NODE_TEST_NS = 4,
+    NODE_TEST_NAME = 5
+} xmlXPathTestVal;
 
-#define NODE_TYPE_COMMENT		50
-#define NODE_TYPE_TEXT			51
-#define NODE_TYPE_PI			52
-#define NODE_TYPE_NODE			53
+typedef enum {
+    NODE_TYPE_COMMENT = 50,
+    NODE_TYPE_TEXT = 51,
+    NODE_TYPE_PI = 52,
+    NODE_TYPE_NODE = 53
+} xmlXPathTypeVal;
 
 #define IS_FUNCTION			200
 
 /**
  * xmlXPathNodeCollectAndTest:
  * @ctxt:  the XPath Parser context
- * @cur:  the current node to test
+ * @axis:  the XPath axis
+ * @test:  the XPath test
+ * @type:  the XPath type
+ * @prefix:  the namesapce prefix if any
+ * @name:  the name used in the search if any
  *
  * This is the function implementing a step: based on the current list
  * of nodes, it builds up a new list, looking at all nodes under that
@@ -1946,9 +2066,10 @@
  *
  * Returns the new NodeSet resulting from the search.
  */
-xmlNodeSetPtr
-xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
-                 int test, int type, const xmlChar *prefix, const xmlChar *name) {
+void
+xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
+                           xmlXPathTestVal test, xmlXPathTypeVal type,
+			   const xmlChar *prefix, const xmlChar *name) {
 #ifdef DEBUG_STEP
     int n = 0, t = 0;
 #endif
@@ -1956,17 +2077,12 @@
     xmlNodeSetPtr ret;
     xmlXPathTraversalFunction next = NULL;
     xmlNodePtr cur = NULL;
+    xmlXPathObjectPtr obj;
+    xmlNodeSetPtr nodelist;
 
-    if (ctxt->context->nodelist == NULL) {
-	if (ctxt->context->node == NULL) {
-	    fprintf(xmlXPathDebug,
-	     "xmlXPathNodeCollectAndTest %s:%d : nodelist and node are NULL\n",
-	            __FILE__, __LINE__);
-	    return(NULL);
-	}
-        STRANGE
-        return(NULL);
-    }
+    CHECK_TYPE(XPATH_NODESET);
+    obj = valuePop(ctxt);
+
 #ifdef DEBUG_STEP
     fprintf(xmlXPathDebug, "new step : ");
 #endif
@@ -2039,11 +2155,14 @@
 #endif
 	    next = xmlXPathNextSelf; break;
     }
-    if (next == NULL) return(NULL);
+    if (next == NULL)
+	return;
+
+    nodelist = obj->nodesetval;
     ret = xmlXPathNodeSetCreate(NULL);
 #ifdef DEBUG_STEP
     fprintf(xmlXPathDebug, " context contains %d nodes\n",
-            ctxt->context->nodelist->nodeNr);
+            nodelist->nodeNr);
     switch (test) {
 	case NODE_TEST_NONE:
 	    fprintf(xmlXPathDebug, "           searching for none !!!\n");
@@ -2070,8 +2189,8 @@
     }
     fprintf(xmlXPathDebug, "Testing : ");
 #endif
-    for (i = 0;i < ctxt->context->nodelist->nodeNr; i++) {
-        ctxt->context->node = ctxt->context->nodelist->nodeTab[i];
+    for (i = 0;i < nodelist->nodeNr; i++) {
+        ctxt->context->node = nodelist->nodeTab[i];
 
 	cur = NULL;
 	do {
@@ -2084,7 +2203,7 @@
 	    switch (test) {
                 case NODE_TEST_NONE:
 		    STRANGE
-		    return(NULL);
+		    return;
                 case NODE_TEST_TYPE:
 		    if ((cur->type == type) ||
 		        ((type == XML_ELEMENT_NODE) && 
@@ -2129,7 +2248,7 @@
 				  ((cur->ns != NULL) && 
 				   (xmlStrEqual(prefix, cur->ns->href)))))) {
 #ifdef DEBUG_STEP
-			    n++;
+				n++;
 #endif
 				xmlXPathNodeSetAdd(ret, cur);
 			    }
@@ -2138,7 +2257,7 @@
 			    xmlAttrPtr attr = (xmlAttrPtr) cur;
 			    if (xmlStrEqual(name, attr->name)) {
 #ifdef DEBUG_STEP
-			    n++;
+				n++;
 #endif
 				xmlXPathNodeSetAdd(ret, cur);
 			    }
@@ -2148,7 +2267,6 @@
 			    break;
 		    }
 	            break;
-		    
 	    }
 	} while (cur != NULL);
     }
@@ -2156,7 +2274,8 @@
     fprintf(xmlXPathDebug,
             "\nExamined %d nodes, found %d nodes at that step\n", t, n);
 #endif
-    return(ret);
+    xmlXPathFreeObject(obj);
+    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
 }
 
 
@@ -2174,10 +2293,15 @@
  */
 void
 xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
-    if (ctxt->context->nodelist != NULL)
-        xmlXPathFreeNodeSet(ctxt->context->nodelist);
+    xmlXPathObjectPtr obj;
+
+    CHECK_TYPE(XPATH_NODESET);
+    obj = valuePop(ctxt);
+
     ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
-    ctxt->context->nodelist = xmlXPathNodeSetCreate(ctxt->context->node);
+
+    xmlXPathFreeObject(obj);
+    valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
 }
 
 /************************************************************************
@@ -2487,6 +2611,12 @@
     cur = valuePop(ctxt);
     if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
     switch (cur->type) {
+	case XPATH_UNDEFINED:
+#ifdef DEBUG_EXPR
+	    fprintf(xmlXPathDebug, "String: undefined\n");
+#endif
+	    valuePush(ctxt, xmlXPathNewCString(""));
+	    break;
         case XPATH_NODESET:
 	    if (cur->nodesetval->nodeNr == 0) {
 		valuePush(ctxt, xmlXPathNewCString(""));
@@ -2522,6 +2652,10 @@
 	    xmlXPathFreeObject(cur);
 	    return;
 	}
+	case XPATH_USERS:
+	    TODO
+	    valuePush(ctxt, xmlXPathNewCString(""));
+	    break;
     }
     STRANGE
 }
@@ -3084,6 +3218,12 @@
     CHECK_ARITY(1);
     cur = valuePop(ctxt);
     switch (cur->type) {
+	case XPATH_UNDEFINED:
+#ifdef DEBUG_EXPR
+	    fprintf(xmlXPathDebug, "NUMBER: undefined\n");
+#endif
+	    valuePush(ctxt, xmlXPathNewFloat(0.0));
+	    break;
         case XPATH_NODESET:
 	    valuePush(ctxt, cur);
 	    xmlXPathStringFunction(ctxt, 1);
@@ -3101,6 +3241,10 @@
 	case XPATH_NUMBER:
 	    valuePush(ctxt, cur);
 	    return;
+	case XPATH_USERS:
+	    TODO
+	    valuePush(ctxt, xmlXPathNewFloat(0.0));
+	    break;
     }
     STRANGE
 }
@@ -3800,8 +3944,6 @@
 
 void
 xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) {
-    xmlNodeSetPtr newset = NULL;
-
     SKIP_BLANKS;
     if ((CUR == '$') || (CUR == '(') || (IS_DIGIT(CUR)) ||
         (CUR == '\'') || (CUR == '"')) {
@@ -3810,15 +3952,8 @@
 	if ((CUR == '/') && (NXT(1) == '/')) {
 	    SKIP(2);
 	    SKIP_BLANKS;
-	    if (ctxt->context->nodelist == NULL) {
-		STRANGE
-		xmlXPathRoot(ctxt);
-	    }
-	    newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
+	    xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
 			     NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
-	    if (ctxt->context->nodelist != NULL)
-		xmlXPathFreeNodeSet(ctxt->context->nodelist);
-	    ctxt->context->nodelist = newset;
 	    ctxt->context->node = NULL;
 	    xmlXPathEvalRelativeLocationPath(ctxt);
 	} else if (CUR == '/') {
@@ -3836,8 +3971,11 @@
 	if (name != NULL)
 	    xmlFree(name);
 
-    if (ctxt->context->nodelist != NULL)
-	valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist));
+#if 0
+	/* DV 1234 !!!!!!! */
+	if (ctxt->context->nodelist != NULL)
+	    valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist));
+#endif
     } 
 }
 
@@ -3857,19 +3995,21 @@
     CHECK_ERROR;
     SKIP_BLANKS;
     if (CUR == '|') {
-	xmlNodeSetPtr old = ctxt->context->nodelist;
+	xmlXPathObjectPtr obj1,obj2;
+
+	CHECK_TYPE(XPATH_NODESET);
+	obj1 = valuePop(ctxt);
+	valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
 
 	NEXT;
 	SKIP_BLANKS;
 	xmlXPathEvalPathExpr(ctxt);
 
-	if (ctxt->context->nodelist == NULL)
-	    ctxt->context->nodelist = old;
-	else {
-	    ctxt->context->nodelist = 
-	        xmlXPathNodeSetMerge(ctxt->context->nodelist, old);
-	    xmlXPathFreeNodeSet(old);
-	}
+	CHECK_TYPE(XPATH_NODESET);
+	obj2 = valuePop(ctxt);
+	obj1->nodesetval = xmlXPathNodeSetMerge(obj1->nodesetval,
+		                                obj2->nodesetval);
+	xmlXPathFreeObject(obj2);
     }
 }
 
@@ -4182,6 +4322,7 @@
 xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
     const xmlChar *cur;
     xmlXPathObjectPtr res;
+    xmlXPathObjectPtr obj, tmp;
     xmlNodeSetPtr newset = NULL;
     xmlNodeSetPtr oldset;
     int i;
@@ -4198,8 +4339,9 @@
      * expression for all the element in the set. use it to grow
      * up a new set.
      */
-    oldset = ctxt->context->nodelist;
-    ctxt->context->nodelist = NULL;
+    CHECK_TYPE(XPATH_NODESET);
+    obj = valuePop(ctxt);
+    oldset = obj->nodesetval;
     ctxt->context->node = NULL;
 
     if ((oldset == NULL) || (oldset->nodeNr == 0)) {
@@ -4210,6 +4352,7 @@
 	res = valuePop(ctxt);
 	if (res != NULL)
 	    xmlXPathFreeObject(res);
+	valuePush(ctxt, obj);
     } else {
 	/*
 	 * Save the expression pointer since we will have to evaluate
@@ -4226,7 +4369,8 @@
 	     * in the nodeset.
 	     */
 	    ctxt->context->node = oldset->nodeTab[i];
-	    ctxt->context->nodelist = NULL;
+	    tmp = xmlXPathNewNodeSet(ctxt->context->node);
+	    valuePush(ctxt, tmp);
 	    ctxt->context->contextSize = oldset->nodeNr;
 	    ctxt->context->proximityPosition = i + 1;
 
@@ -4241,8 +4385,16 @@
 	    if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
 	        xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
 	    }
+
+	    /*
+	     * Cleanup
+	     */
 	    if (res != NULL)
 		xmlXPathFreeObject(res);
+	    if (ctxt->value == tmp) {
+		res = valuePop(ctxt);
+		xmlXPathFreeObject(res);
+	    }
 	    
 	    ctxt->context->node = NULL;
 	}
@@ -4250,22 +4402,21 @@
 	/*
 	 * The result is used as the new evaluation set.
 	 */
-	ctxt->context->nodelist = newset;
+	xmlXPathFreeObject(obj);
 	ctxt->context->node = NULL;
 	ctxt->context->contextSize = -1;
 	ctxt->context->proximityPosition = -1;
+	valuePush(ctxt, xmlXPathWrapNodeSet(newset));
     }
     if (CUR != ']') {
 	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
     }
-    if (oldset != NULL)
-	xmlXPathFreeNodeSet(oldset);
 
     NEXT;
     SKIP_BLANKS;
 #ifdef DEBUG_STEP
     fprintf(xmlXPathDebug, "After predicate : ");
-    xmlXPathDebugNodeSet(xmlXPathDebug, ctxt->context->nodelist);
+    xmlXPathDebugNodeSet(xmlXPathDebug, ctxt->context->value->nodesetval);
 #endif
 }
 
@@ -4290,11 +4441,10 @@
 xmlXPathEvalBasis(xmlXPathParserContextPtr ctxt) {
     xmlChar *name = NULL;
     xmlChar *prefix = NULL;
-    int type = 0;
-    int axis = AXIS_CHILD; /* the default on abbreviated syntax */
-    int nodetest = NODE_TEST_NONE;
-    int nodetype = 0;
-    xmlNodeSetPtr newset = NULL;
+    xmlXPathTypeVal type = 0;
+    xmlXPathAxisVal axis = AXIS_CHILD; /* the default on abbreviated syntax */
+    xmlXPathTestVal nodetest = NODE_TEST_NONE;
+    xmlElementType nodetype = 0;
 
     if (CUR == '@') {
         NEXT;
@@ -4344,17 +4494,6 @@
 		NEXT;
 		xmlFree(name);
 		func(ctxt, nbargs);
-		if ((ctxt->value != top) &&
-		    (ctxt->value != NULL) &&
-		    (ctxt->value->type == XPATH_NODESET)) {
-		    xmlXPathObjectPtr cur;
-
-		    cur = valuePop(ctxt);
-		    ctxt->context->nodelist = cur->nodesetval;
-		    ctxt->context->node = NULL;
-		    cur->nodesetval = NULL;
-                    xmlXPathFreeObject(cur);
-		}
 	        return;
 	    }
 	    /*
@@ -4522,15 +4661,11 @@
 #ifdef DEBUG_STEP
     fprintf(xmlXPathDebug, "Basis : computing new set\n");
 #endif
-    newset = xmlXPathNodeCollectAndTest(ctxt, axis, nodetest, nodetype,
+    xmlXPathNodeCollectAndTest(ctxt, axis, nodetest, nodetype,
                                         prefix, name);
-    if (ctxt->context->nodelist != NULL)
-	xmlXPathFreeNodeSet(ctxt->context->nodelist);
-    ctxt->context->nodelist = newset;
-    ctxt->context->node = NULL;
 #ifdef DEBUG_STEP
     fprintf(xmlXPathDebug, "Basis : ");
-    xmlXPathDebugNodeSet(stdout, ctxt->context->nodelist);
+    xmlXPathDebugNodeSet(stdout, ctxt->context->value->nodesetval);
 #endif
     if (name != NULL) xmlFree(name);
     if (prefix != NULL) xmlFree(prefix);
@@ -4559,22 +4694,12 @@
  */
 void
 xmlXPathEvalStep(xmlXPathParserContextPtr ctxt) {
-    xmlNodeSetPtr newset = NULL;
-
     SKIP_BLANKS;
     if ((CUR == '.') && (NXT(1) == '.')) {
 	SKIP(2);
 	SKIP_BLANKS;
-	if (ctxt->context->nodelist == NULL) {
-	    STRANGE
-	    xmlXPathRoot(ctxt);
-	}
-	newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_PARENT,
+	xmlXPathNodeCollectAndTest(ctxt, AXIS_PARENT,
 			 NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
-	if (ctxt->context->nodelist != NULL)
-	    xmlXPathFreeNodeSet(ctxt->context->nodelist);
-	ctxt->context->nodelist = newset;
-	ctxt->context->node = NULL;
     } else if (CUR == '.') {
 	NEXT;
 	SKIP_BLANKS;
@@ -4608,8 +4733,6 @@
  */
 void
 xmlXPathEvalRelativeLocationPath(xmlXPathParserContextPtr ctxt) {
-    xmlNodeSetPtr newset = NULL;
-
     SKIP_BLANKS;
     xmlXPathEvalStep(ctxt);
     SKIP_BLANKS;
@@ -4617,16 +4740,8 @@
 	if ((CUR == '/') && (NXT(1) == '/')) {
 	    SKIP(2);
 	    SKIP_BLANKS;
-	    if (ctxt->context->nodelist == NULL) {
-		STRANGE
-		xmlXPathRoot(ctxt);
-	    }
-	    newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
+	    xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
 			     NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
-	    if (ctxt->context->nodelist != NULL)
-		xmlXPathFreeNodeSet(ctxt->context->nodelist);
-	    ctxt->context->nodelist = newset;
-	    ctxt->context->node = NULL;
 	    xmlXPathEvalStep(ctxt);
 	} else if (CUR == '/') {
 	    NEXT;
@@ -4658,8 +4773,6 @@
  */
 void
 xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) {
-    xmlNodeSetPtr newset = NULL;
-
     SKIP_BLANKS;
     if (CUR != '/') {
         xmlXPathEvalRelativeLocationPath(ctxt);
@@ -4668,15 +4781,9 @@
 	    if ((CUR == '/') && (NXT(1) == '/')) {
 		SKIP(2);
 		SKIP_BLANKS;
-		if (ctxt->context->nodelist == NULL)
-		    xmlXPathRoot(ctxt);
-		newset = xmlXPathNodeCollectAndTest(ctxt,
+		xmlXPathNodeCollectAndTest(ctxt,
 		                 AXIS_DESCENDANT_OR_SELF, NODE_TEST_TYPE,
 				 XML_ELEMENT_NODE, NULL, NULL);
-		if (ctxt->context->nodelist != NULL)
-		    xmlXPathFreeNodeSet(ctxt->context->nodelist);
-		ctxt->context->nodelist = newset;
-		ctxt->context->node = NULL;
 		xmlXPathEvalRelativeLocationPath(ctxt);
 	    } else if (CUR == '/') {
 		NEXT;
@@ -4694,7 +4801,7 @@
 /**
  * xmlXPathEval:
  * @str:  the XPath expression
- * @ctxt:  the XPath context
+ * @ctx:  the XPath context
  *
  * Evaluate the XPath Location Path in the given context.
  *
@@ -4702,25 +4809,32 @@
  *         the caller has to free the object.
  */
 xmlXPathObjectPtr
-xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) {
-    xmlXPathParserContextPtr pctxt;
+xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
+    xmlXPathParserContextPtr ctxt;
     xmlXPathObjectPtr res = NULL, tmp;
     int stack = 0;
 
     xmlXPathInit();
 
-    CHECK_CONTEXT
+    CHECK_CONTEXT(ctx)
 
     if (xmlXPathDebug == NULL)
         xmlXPathDebug = stderr;
-    pctxt = xmlXPathNewParserContext(str, ctxt);
+    ctxt = xmlXPathNewParserContext(str, ctx);
+    valuePush(ctxt, xmlXPathNewNodeSet(ctx->node));
     if (str[0] == '/')
-        xmlXPathRoot(pctxt);
-    xmlXPathEvalLocationPath(pctxt);
+        xmlXPathRoot(ctxt);
+    xmlXPathEvalLocationPath(ctxt);
 
-    /* TODO: cleanup nodelist, res = valuePop(pctxt); */
+    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
+	fprintf(xmlXPathDebug,
+		"xmlXPathEval: evaluation failed to return a node set\n");
+    } else {
+	res = valuePop(ctxt);
+    }
+
     do {
-        tmp = valuePop(pctxt);
+        tmp = valuePop(ctxt);
 	if (tmp != NULL) {
 	    xmlXPathFreeObject(tmp);
 	    stack++;    
@@ -4730,12 +4844,12 @@
 	fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n",
 	        stack);
     }
-    if (pctxt->error == XPATH_EXPRESSION_OK)
-	res = xmlXPathNewNodeSetList(pctxt->context->nodelist);
-    else
-        res = NULL;
+    if (ctxt->error != XPATH_EXPRESSION_OK) {
+	xmlXPathFreeObject(res);
+	res = NULL;
+    }
         
-    xmlXPathFreeParserContext(pctxt);
+    xmlXPathFreeParserContext(ctxt);
     return(res);
 }
 
@@ -4757,7 +4871,7 @@
 
     xmlXPathInit();
 
-    CHECK_CONTEXT
+    CHECK_CONTEXT(ctxt)
 
     if (xmlXPathDebug == NULL)
         xmlXPathDebug = stderr;
diff --git a/xpath.h b/xpath.h
index 0efe466..6c5f42e 100644
--- a/xpath.h
+++ b/xpath.h
@@ -143,7 +143,6 @@
 struct _xmlXPathContext {
     xmlDocPtr doc;			/* The current document */
     xmlNodePtr node;			/* The current node */
-    xmlNodeSetPtr nodelist;		/* The current node list */
 
     int nb_variables;			/* number of defined variables */
     int max_variables;			/* max number of variables */