adding the tree debug mode fixing various problems reported by the debug

* debugXML.c include/libxml/debugXML.h include/libxml/xmlerror.h:
  adding the tree debug mode
* parser.c relaxng.c tree.c xpath.c: fixing various problems reported
  by the debug mode.
* SAX2.c: another tree fix from Rob Richards
Daniel
diff --git a/ChangeLog b/ChangeLog
index 40cfb08..9a626b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu Oct  7 15:12:58 CEST 2004 Daniel Veillard <daniel@veillard.com>
+
+	* debugXML.c include/libxml/debugXML.h include/libxml/xmlerror.h:
+	  adding the tree debug mode
+	* parser.c relaxng.c tree.c xpath.c: fixing various problems reported
+	  by the debug mode.
+	* SAX2.c: another tree fix from Rob Richards
+
 Wed Oct  6 10:50:03 PDT 2004 William Brack <wbrack@mmm.com.hk>
 
 	* catalog.c: small change to last fix, to get xml:base right
diff --git a/SAX2.c b/SAX2.c
index fc0a8bf..c41af00 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -1824,6 +1824,7 @@
 						    valueend - value);
 	    tmp = ret->children;
 	    while (tmp != NULL) {
+	        tmp->doc = ret->doc;
 		tmp->parent = (xmlNodePtr) ret;
 		if (tmp->next == NULL)
 		    ret->last = tmp;
diff --git a/debugXML.c b/debugXML.c
index 1980441..00f29e0 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -41,7 +41,9 @@
     char shift[101];            /* used for indenting */
     int depth;                  /* current depth */
     xmlDocPtr doc;              /* current document */
+    xmlNodePtr node;		/* current node */
     int check;                  /* do just checkings */
+    int errors;                 /* number of errors found */
 };
 
 static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
@@ -53,6 +55,7 @@
 
     ctxt->depth = 0;
     ctxt->check = 0;
+    ctxt->errors = 0;
     ctxt->output = stdout;
     for (i = 0; i < 100; i++)
         ctxt->shift[i] = ' ';
@@ -72,6 +75,83 @@
     }
 }
 
+/**
+ * xmlDebugErr:
+ * @ctxt:  a debug context
+ * @error:  the error code
+ *
+ * Handle a debug error.
+ */
+static void
+xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
+{
+    ctxt->errors++;
+    __xmlRaiseError(NULL, NULL, NULL,
+		    NULL, ctxt->node, XML_FROM_CHECK,
+		    error, XML_ERR_ERROR, NULL, 0,
+		    NULL, NULL, NULL, 0, 0,
+		    msg);
+}
+static void
+xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
+{
+    ctxt->errors++;
+    __xmlRaiseError(NULL, NULL, NULL,
+		    NULL, ctxt->node, XML_FROM_CHECK,
+		    error, XML_ERR_ERROR, NULL, 0,
+		    NULL, NULL, NULL, 0, 0,
+		    msg, extra);
+}
+static void
+xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, char *extra)
+{
+    ctxt->errors++;
+    __xmlRaiseError(NULL, NULL, NULL,
+		    NULL, ctxt->node, XML_FROM_CHECK,
+		    error, XML_ERR_ERROR, NULL, 0,
+		    NULL, NULL, NULL, 0, 0,
+		    msg, extra);
+}
+
+static void
+xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
+    if (node->parent == NULL)
+        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
+	            "Node has no parent\n");
+    if (node->doc == NULL)
+        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
+	            "Node has no doc\n");
+    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
+        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
+        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
+	            "Node doc differs from parent's one\n");
+    if (node->prev == NULL) {
+        if (node->type == XML_ATTRIBUTE_NODE) {
+	    if ((node->parent != NULL) &&
+	        (node != (xmlNodePtr) node->parent->properties))
+		xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
+                    "Attr has no prev and not first of attr list\n");
+	        
+        } else if ((node->parent != NULL) && (node->parent->children != node))
+	    xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
+                    "Node has no prev and not first of parent list\n");
+    } else {
+        if (node->prev->next != node)
+	    xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
+                        "Node prev->next : back link wrong\n");
+    }
+    if (node->next == NULL) {
+	if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
+	    (node->parent->last != node))
+	    xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
+                    "Node has no next and not last of parent list\n");
+    } else {
+        if (node->next->prev != node)
+	    xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
+                    "Node next->prev : forward link wrong\n");
+    }
+}
+
 static void
 xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
 {
@@ -108,7 +188,8 @@
     }
 
     if (dtd->type != XML_DTD_NODE) {
-        fprintf(ctxt->output, "PBM: not a DTD\n");
+	xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
+	            "Node is not a DTD");
         return;
     }
     if (!ctxt->check) {
@@ -125,32 +206,7 @@
     /*
      * Do a bit of checking
      */
-    if (dtd->parent == NULL)
-        fprintf(ctxt->output, "PBM: DTD has no parent\n");
-    if (dtd->doc == NULL)
-        fprintf(ctxt->output, "PBM: DTD has no doc\n");
-    if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
-        fprintf(ctxt->output, "PBM: DTD doc differs from parent's one\n");
-    if (dtd->prev == NULL) {
-        if ((dtd->parent != NULL)
-            && (dtd->parent->children != (xmlNodePtr) dtd))
-            fprintf(ctxt->output,
-                    "PBM: DTD has no prev and not first of list\n");
-    } else {
-        if (dtd->prev->next != (xmlNodePtr) dtd)
-            fprintf(ctxt->output,
-                    "PBM: DTD prev->next : back link wrong\n");
-    }
-    if (dtd->next == NULL) {
-        if ((dtd->parent != NULL)
-            && (dtd->parent->last != (xmlNodePtr) dtd))
-            fprintf(ctxt->output,
-                    "PBM: DTD has no next and not last of list\n");
-    } else {
-        if (dtd->next->prev != (xmlNodePtr) dtd)
-            fprintf(ctxt->output,
-                    "PBM: DTD next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
 }
 
 static void
@@ -164,19 +220,22 @@
         return;
     }
     if (attr->type != XML_ATTRIBUTE_DECL) {
-        fprintf(ctxt->output, "PBM: not a Attr\n");
+	xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
+	            "Node is not an attribute declaration");
         return;
     }
     if (attr->name != NULL) {
         if (!ctxt->check)
             fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
     } else
-        fprintf(ctxt->output, "PBM ATTRDECL noname!!!");
+	xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
+	            "Node attribute declaration has no name");
     if (attr->elem != NULL) {
         if (!ctxt->check)
             fprintf(ctxt->output, " for %s", (char *) attr->elem);
     } else
-        fprintf(ctxt->output, " PBM noelem!!!");
+	xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
+	            "Node attribute declaration has no element name");
     if (!ctxt->check) {
         switch (attr->atype) {
             case XML_ATTRIBUTE_CDATA:
@@ -252,32 +311,7 @@
     /*
      * Do a bit of checking
      */
-    if (attr->parent == NULL)
-        fprintf(ctxt->output, "PBM: Attr has no parent\n");
-    if (attr->doc == NULL)
-        fprintf(ctxt->output, "PBM: Attr has no doc\n");
-    if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
-        fprintf(ctxt->output, "PBM: Attr doc differs from parent's one\n");
-    if (attr->prev == NULL) {
-        if ((attr->parent != NULL)
-            && (attr->parent->children != (xmlNodePtr) attr))
-            fprintf(ctxt->output,
-                    "PBM: Attr has no prev and not first of list\n");
-    } else {
-        if (attr->prev->next != (xmlNodePtr) attr)
-            fprintf(ctxt->output,
-                    "PBM: Attr prev->next : back link wrong\n");
-    }
-    if (attr->next == NULL) {
-        if ((attr->parent != NULL)
-            && (attr->parent->last != (xmlNodePtr) attr))
-            fprintf(ctxt->output,
-                    "PBM: Attr has no next and not last of list\n");
-    } else {
-        if (attr->next->prev != (xmlNodePtr) attr)
-            fprintf(ctxt->output,
-                    "PBM: Attr next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
 }
 
 static void
@@ -291,7 +325,8 @@
         return;
     }
     if (elem->type != XML_ELEMENT_DECL) {
-        fprintf(ctxt->output, "PBM: not a Elem\n");
+	xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
+	            "Node is not an element declaration");
         return;
     }
     if (elem->name != NULL) {
@@ -301,7 +336,8 @@
             fprintf(ctxt->output, ")");
         }
     } else
-        fprintf(ctxt->output, "PBM ELEMDECL noname!!!");
+	xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
+	            "Element declaration has no name");
     if (!ctxt->check) {
         switch (elem->etype) {
             case XML_ELEMENT_TYPE_UNDEFINED:
@@ -334,32 +370,7 @@
     /*
      * Do a bit of checking
      */
-    if (elem->parent == NULL)
-        fprintf(ctxt->output, "PBM: Elem has no parent\n");
-    if (elem->doc == NULL)
-        fprintf(ctxt->output, "PBM: Elem has no doc\n");
-    if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
-        fprintf(ctxt->output, "PBM: Elem doc differs from parent's one\n");
-    if (elem->prev == NULL) {
-        if ((elem->parent != NULL)
-            && (elem->parent->children != (xmlNodePtr) elem))
-            fprintf(ctxt->output,
-                    "PBM: Elem has no prev and not first of list\n");
-    } else {
-        if (elem->prev->next != (xmlNodePtr) elem)
-            fprintf(ctxt->output,
-                    "PBM: Elem prev->next : back link wrong\n");
-    }
-    if (elem->next == NULL) {
-        if ((elem->parent != NULL)
-            && (elem->parent->last != (xmlNodePtr) elem))
-            fprintf(ctxt->output,
-                    "PBM: Elem has no next and not last of list\n");
-    } else {
-        if (elem->next->prev != (xmlNodePtr) elem)
-            fprintf(ctxt->output,
-                    "PBM: Elem next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
 }
 
 static void
@@ -373,7 +384,8 @@
         return;
     }
     if (ent->type != XML_ENTITY_DECL) {
-        fprintf(ctxt->output, "PBM: not a Entity decl\n");
+	xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
+	            "Node is not an entity declaration");
         return;
     }
     if (ent->name != NULL) {
@@ -383,7 +395,8 @@
             fprintf(ctxt->output, ")");
         }
     } else
-        fprintf(ctxt->output, "PBM ENTITYDECL noname!!!");
+	xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
+	            "Entity declaration has no name");
     if (!ctxt->check) {
         switch (ent->etype) {
             case XML_INTERNAL_GENERAL_ENTITY:
@@ -430,32 +443,7 @@
     /*
      * Do a bit of checking
      */
-    if (ent->parent == NULL)
-        fprintf(ctxt->output, "PBM: Ent has no parent\n");
-    if (ent->doc == NULL)
-        fprintf(ctxt->output, "PBM: Ent has no doc\n");
-    if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
-        fprintf(ctxt->output, "PBM: Ent doc differs from parent's one\n");
-    if (ent->prev == NULL) {
-        if ((ent->parent != NULL)
-            && (ent->parent->children != (xmlNodePtr) ent))
-            fprintf(ctxt->output,
-                    "PBM: Ent has no prev and not first of list\n");
-    } else {
-        if (ent->prev->next != (xmlNodePtr) ent)
-            fprintf(ctxt->output,
-                    "PBM: Ent prev->next : back link wrong\n");
-    }
-    if (ent->next == NULL) {
-        if ((ent->parent != NULL)
-            && (ent->parent->last != (xmlNodePtr) ent))
-            fprintf(ctxt->output,
-                    "PBM: Ent has no next and not last of list\n");
-    } else {
-        if (ent->next->prev != (xmlNodePtr) ent)
-            fprintf(ctxt->output,
-                    "PBM: Ent next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
 }
 
 static void
@@ -469,17 +457,18 @@
         return;
     }
     if (ns->type != XML_NAMESPACE_DECL) {
-        fprintf(ctxt->output, "invalid namespace type %d\n", ns->type);
+	xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
+	            "Node is not a namespace declaration");
         return;
     }
     if (ns->href == NULL) {
         if (ns->prefix != NULL)
-            fprintf(ctxt->output,
-                    "PBM: incomplete namespace %s href=NULL\n",
+	    xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
+                    "Incomplete namespace %s href=NULL\n",
                     (char *) ns->prefix);
         else
-            fprintf(ctxt->output,
-                    "PBM: incomplete default namespace href=NULL\n");
+	    xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
+                    "Incomplete default namespace href=NULL\n");
     } else {
         if (!ctxt->check) {
             if (ns->prefix != NULL)
@@ -576,7 +565,7 @@
     }
     if (!ctxt->check) {
         fprintf(ctxt->output, "ATTRIBUTE ");
-        xmlCtxtDumpString(ctxt, attr->name);
+	xmlCtxtDumpString(ctxt, attr->name);
         fprintf(ctxt->output, "\n");
         if (attr->children != NULL) {
             ctxt->depth++;
@@ -584,30 +573,14 @@
             ctxt->depth--;
         }
     }
+    if (attr->name == NULL)
+	xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
+	            "Attribute has no name");
 
     /*
      * Do a bit of checking
      */
-    if (attr->parent == NULL)
-        fprintf(ctxt->output, "PBM: Attr has no parent\n");
-    if (attr->doc == NULL)
-        fprintf(ctxt->output, "PBM: Attr has no doc\n");
-    if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
-        fprintf(ctxt->output, "PBM: Attr doc differs from parent's one\n");
-    if (attr->prev == NULL) {
-        if ((attr->parent != NULL) && (attr->parent->properties != attr))
-            fprintf(ctxt->output,
-                    "PBM: Attr has no prev and not first of list\n");
-    } else {
-        if (attr->prev->next != attr)
-            fprintf(ctxt->output,
-                    "PBM: Attr prev->next : back link wrong\n");
-    }
-    if (attr->next != NULL) {
-        if (attr->next->prev != attr)
-            fprintf(ctxt->output,
-                    "PBM: Attr next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
 }
 
 /**
@@ -645,6 +618,8 @@
         }
         return;
     }
+    ctxt->node = node;
+
     switch (node->type) {
         case XML_ELEMENT_NODE:
             if (!ctxt->check) {
@@ -758,7 +733,8 @@
         default:
             if (!ctxt->check)
                 xmlCtxtDumpSpaces(ctxt);
-            fprintf(ctxt->output, "PBM: NODE_%d !!!\n", node->type);
+	    xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
+	                "Unknown node type %d\n", node->type);
             return;
     }
     if (node->doc == NULL) {
@@ -793,30 +769,7 @@
     /*
      * Do a bit of checking
      */
-    if (node->parent == NULL)
-        fprintf(ctxt->output, "PBM: Node has no parent\n");
-    if (node->doc == NULL)
-        fprintf(ctxt->output, "PBM: Node has no doc\n");
-    if ((node->parent != NULL) && (node->doc != node->parent->doc))
-        fprintf(ctxt->output, "PBM: Node doc differs from parent's one\n");
-    if (node->prev == NULL) {
-        if ((node->parent != NULL) && (node->parent->children != node))
-            fprintf(ctxt->output,
-                    "PBM: Node has no prev and not first of list\n");
-    } else {
-        if (node->prev->next != node)
-            fprintf(ctxt->output,
-                    "PBM: Node prev->next : back link wrong\n");
-    }
-    if (node->next == NULL) {
-        if ((node->parent != NULL) && (node->parent->last != node))
-            fprintf(ctxt->output,
-                    "PBM: Node has no next and not last of list\n");
-    } else {
-        if (node->next->prev != node)
-            fprintf(ctxt->output,
-                    "PBM: Node next->prev : forward link wrong\n");
-    }
+    xmlCtxtGenericNodeCheck(ctxt, node);
 }
 
 /**
@@ -862,6 +815,74 @@
     }
 }
 
+static void
+xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
+{
+    if (doc == NULL) {
+        if (!ctxt->check)
+            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
+        return;
+    }
+    ctxt->node = (xmlNodePtr) doc;
+
+    switch (doc->type) {
+        case XML_ELEMENT_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
+	                "Misplaced ELEMENT node\n");
+            break;
+        case XML_ATTRIBUTE_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
+	                "Misplaced ATTRIBUTE node\n");
+            break;
+        case XML_TEXT_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
+	                "Misplaced TEXT node\n");
+            break;
+        case XML_CDATA_SECTION_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
+	                "Misplaced CDATA node\n");
+            break;
+        case XML_ENTITY_REF_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
+	                "Misplaced ENTITYREF node\n");
+            break;
+        case XML_ENTITY_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
+	                "Misplaced ENTITY node\n");
+            break;
+        case XML_PI_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
+	                "Misplaced PI node\n");
+            break;
+        case XML_COMMENT_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
+	                "Misplaced COMMENT node\n");
+            break;
+        case XML_DOCUMENT_NODE:
+	    if (!ctxt->check)
+		fprintf(ctxt->output, "DOCUMENT\n");
+            break;
+        case XML_HTML_DOCUMENT_NODE:
+	    if (!ctxt->check)
+		fprintf(ctxt->output, "HTML DOCUMENT\n");
+            break;
+        case XML_DOCUMENT_TYPE_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
+	                "Misplaced DOCTYPE node\n");
+            break;
+        case XML_DOCUMENT_FRAG_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
+	                "Misplaced FRAGMENT node\n");
+            break;
+        case XML_NOTATION_NODE:
+	    xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
+	                "Misplaced NOTATION node\n");
+            break;
+        default:
+	    xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
+	                "Unknown node type %d\n", doc->type);
+    }
+}
 
 /**
  * xmlCtxtDumpDocumentHead:
@@ -873,55 +894,7 @@
 static void
 xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 {
-    if (doc == NULL) {
-        if (!ctxt->check)
-            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
-        return;
-    }
-
-    switch (doc->type) {
-        case XML_ELEMENT_NODE:
-            fprintf(ctxt->output, "Error, ELEMENT found here ");
-            break;
-        case XML_ATTRIBUTE_NODE:
-            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
-            break;
-        case XML_TEXT_NODE:
-            fprintf(ctxt->output, "Error, TEXT\n");
-            break;
-        case XML_CDATA_SECTION_NODE:
-            fprintf(ctxt->output, "Error, CDATA_SECTION\n");
-            break;
-        case XML_ENTITY_REF_NODE:
-            fprintf(ctxt->output, "Error, ENTITY_REF\n");
-            break;
-        case XML_ENTITY_NODE:
-            fprintf(ctxt->output, "Error, ENTITY\n");
-            break;
-        case XML_PI_NODE:
-            fprintf(ctxt->output, "Error, PI\n");
-            break;
-        case XML_COMMENT_NODE:
-            fprintf(ctxt->output, "Error, COMMENT\n");
-            break;
-        case XML_DOCUMENT_NODE:
-            fprintf(ctxt->output, "DOCUMENT\n");
-            break;
-        case XML_HTML_DOCUMENT_NODE:
-            fprintf(ctxt->output, "HTML DOCUMENT\n");
-            break;
-        case XML_DOCUMENT_TYPE_NODE:
-            fprintf(ctxt->output, "Error, DOCUMENT_TYPE\n");
-            break;
-        case XML_DOCUMENT_FRAG_NODE:
-            fprintf(ctxt->output, "Error, DOCUMENT_FRAG\n");
-            break;
-        case XML_NOTATION_NODE:
-            fprintf(ctxt->output, "Error, NOTATION\n");
-            break;
-        default:
-            fprintf(ctxt->output, "NODE_%d\n", doc->type);
-    }
+    xmlCtxtDumpDocHead(ctxt, doc);
     if (!ctxt->check) {
         if (doc->name != NULL) {
             fprintf(ctxt->output, "name=");
@@ -1002,7 +975,8 @@
                 fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
                 break;
             default:
-                fprintf(ctxt->output, "UNKNOWN TYPE %d", cur->etype);
+		xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
+			     "Unknown entity type %d\n", cur->etype);
         }
         if (cur->ExternalID != NULL)
             fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
@@ -1027,55 +1001,7 @@
 static void
 xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
 {
-    if (doc == NULL) {
-        if (!ctxt->check)
-            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
-        return;
-    }
-
-    switch (doc->type) {
-        case XML_ELEMENT_NODE:
-            fprintf(ctxt->output, "Error, ELEMENT found here ");
-            break;
-        case XML_ATTRIBUTE_NODE:
-            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
-            break;
-        case XML_TEXT_NODE:
-            fprintf(ctxt->output, "Error, TEXT\n");
-            break;
-        case XML_CDATA_SECTION_NODE:
-            fprintf(ctxt->output, "Error, CDATA_SECTION\n");
-            break;
-        case XML_ENTITY_REF_NODE:
-            fprintf(ctxt->output, "Error, ENTITY_REF\n");
-            break;
-        case XML_ENTITY_NODE:
-            fprintf(ctxt->output, "Error, ENTITY\n");
-            break;
-        case XML_PI_NODE:
-            fprintf(ctxt->output, "Error, PI\n");
-            break;
-        case XML_COMMENT_NODE:
-            fprintf(ctxt->output, "Error, COMMENT\n");
-            break;
-        case XML_DOCUMENT_NODE:
-            fprintf(ctxt->output, "DOCUMENT\n");
-            break;
-        case XML_HTML_DOCUMENT_NODE:
-            fprintf(ctxt->output, "HTML DOCUMENT\n");
-            break;
-        case XML_DOCUMENT_TYPE_NODE:
-            fprintf(ctxt->output, "Error, DOCUMENT_TYPE\n");
-            break;
-        case XML_DOCUMENT_FRAG_NODE:
-            fprintf(ctxt->output, "Error, DOCUMENT_FRAG\n");
-            break;
-        case XML_NOTATION_NODE:
-            fprintf(ctxt->output, "Error, NOTATION\n");
-            break;
-        default:
-            fprintf(ctxt->output, "NODE_%d\n", doc->type);
-    }
+    xmlCtxtDumpDocHead(ctxt, doc);
     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
             doc->intSubset->entities;
@@ -1113,46 +1039,7 @@
             fprintf(ctxt->output, "DTD is NULL\n");
         return;
     }
-    if (dtd->type != XML_DTD_NODE) {
-        fprintf(ctxt->output, "PBM: not a DTD\n");
-        return;
-    }
-    if (!ctxt->check) {
-        if (dtd->name != NULL)
-            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
-        else
-            fprintf(ctxt->output, "DTD");
-        if (dtd->ExternalID != NULL)
-            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
-        if (dtd->SystemID != NULL)
-            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
-        fprintf(ctxt->output, "\n");
-    }
-    /*
-     * Do a bit of checking
-     */
-    if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
-        fprintf(ctxt->output, "PBM: DTD doc differs from parent's one\n");
-    if (dtd->prev == NULL) {
-        if ((dtd->parent != NULL)
-            && (dtd->parent->children != (xmlNodePtr) dtd))
-            fprintf(ctxt->output,
-                    "PBM: DTD has no prev and not first of list\n");
-    } else {
-        if (dtd->prev->next != (xmlNodePtr) dtd)
-            fprintf(ctxt->output,
-                    "PBM: DTD prev->next : back link wrong\n");
-    }
-    if (dtd->next == NULL) {
-        if ((dtd->parent != NULL)
-            && (dtd->parent->last != (xmlNodePtr) dtd))
-            fprintf(ctxt->output,
-                    "PBM: DTD has no next and not last of list\n");
-    } else {
-        if (dtd->next->prev != (xmlNodePtr) dtd)
-            fprintf(ctxt->output,
-                    "PBM: DTD next->prev : forward link wrong\n");
-    }
+    xmlCtxtDumpDtdNode(ctxt, dtd);
     if (dtd->children == NULL)
         fprintf(ctxt->output, "    DTD is empty\n");
     else {
@@ -1161,9 +1048,10 @@
         ctxt->depth--;
     }
 }
+
 /************************************************************************
  *									*
- *			Public entry points				*
+ *			Public entry points for dump			*
  *									*
  ************************************************************************/
 
@@ -1372,6 +1260,36 @@
 
 /************************************************************************
  *									*
+ *			Public entry points for checkings		*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlDebugCheckDocument:
+ * @output:  the FILE * for the output
+ * @doc:  the document
+ *
+ * Check the document for potential content problems, and output
+ * the errors to @output
+ *
+ * Returns the number of errors found
+ */
+int
+xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
+{
+    xmlDebugCtxt ctxt;
+
+    if (output == NULL)
+	output = stdout;
+    xmlCtxtDumpInitCtxt(&ctxt);
+    ctxt.output = output;
+    ctxt.check = 1;
+    xmlCtxtDumpDocument(&ctxt, doc);
+    return(ctxt.errors);
+}
+
+/************************************************************************
+ *									*
  *			Helpers for Shell				*
  *									*
  ************************************************************************/
diff --git a/include/libxml/debugXML.h b/include/libxml/debugXML.h
index 85966e5..d3b123c 100644
--- a/include/libxml/debugXML.h
+++ b/include/libxml/debugXML.h
@@ -61,6 +61,22 @@
 	xmlDebugDumpEntities	(FILE *output,
 				 xmlDocPtr doc);
 
+/****************************************************************
+ *								*
+ *	 		Checking routines			*
+ *								*
+ ****************************************************************/
+
+XMLPUBFUN int XMLCALL
+	xmlDebugCheckDocument	(FILE * output,
+				 xmlDocPtr doc);
+
+/****************************************************************
+ *								*
+ *	 		XML shell helpers			*
+ *								*
+ ****************************************************************/
+
 XMLPUBFUN void XMLCALL	
 	xmlLsOneNode		(FILE *output, xmlNodePtr node);
 XMLPUBFUN int XMLCALL	
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index a991256..aeabda7 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -57,7 +57,8 @@
     XML_FROM_CATALOG,	/* The Catalog module */
     XML_FROM_C14N,	/* The Canonicalization module */
     XML_FROM_XSLT,	/* The XSLT engine from libxslt */
-    XML_FROM_VALID	/* The XML DTD validation with valid context */
+    XML_FROM_VALID,	/* The XML DTD validation with valid context */
+    XML_FROM_CHECK	/* The error checking module */
 } xmlErrorDomain;
 
 /**
@@ -743,7 +744,44 @@
     XML_SCHEMAP_SRC_CT_1, /* 3076 */
     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */
     XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */
-    XML_SCHEMAP_A_PROPS_CORRECT_2
+    XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */
+    XML_CHECK_FOUND_ELEMENT = 5000,
+    XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */
+    XML_CHECK_FOUND_TEXT, /* 5002 */
+    XML_CHECK_FOUND_CDATA, /* 5003 */
+    XML_CHECK_FOUND_ENTITYREF, /* 5004 */
+    XML_CHECK_FOUND_ENTITY, /* 5005 */
+    XML_CHECK_FOUND_PI, /* 5006 */
+    XML_CHECK_FOUND_COMMENT, /* 5007 */
+    XML_CHECK_FOUND_DOCTYPE, /* 5008 */
+    XML_CHECK_FOUND_FRAGMENT, /* 5009 */
+    XML_CHECK_FOUND_NOTATION, /* 5010 */
+    XML_CHECK_UNKNOWN_NODE, /* 5011 */
+    XML_CHECK_ENTITY_TYPE, /* 5012 */
+    XML_CHECK_NO_PARENT, /* 5013 */
+    XML_CHECK_NO_DOC, /* 5014 */
+    XML_CHECK_NO_NAME, /* 5015 */
+    XML_CHECK_NO_ELEM, /* 5016 */
+    XML_CHECK_WRONG_DOC, /* 5017 */
+    XML_CHECK_NO_PREV, /* 5018 */
+    XML_CHECK_WRONG_PREV, /* 5019 */
+    XML_CHECK_NO_NEXT, /* 5020 */
+    XML_CHECK_WRONG_NEXT, /* 5021 */
+    XML_CHECK_NOT_DTD, /* 5022 */
+    XML_CHECK_NOT_ATTR, /* 5023 */
+    XML_CHECK_NOT_ATTR_DECL, /* 5024 */
+    XML_CHECK_NOT_ELEM_DECL, /* 5025 */
+    XML_CHECK_NOT_ENTITY_DECL, /* 5026 */
+    XML_CHECK_NOT_NS_DECL, /* 5027 */
+    XML_CHECK_NO_HREF, /* 5028 */
+    XML_CHECK_ /* 5029 */
+#if 0
+    XML_CHECK_, /* 5030 */
+    XML_CHECK_, /* 5031 */
+    XML_CHECK_, /* 5032 */
+    XML_CHECK_, /* 5033 */
+    XML_CHECK_X /* 503 */
+#endif
 } xmlParserErrors;
 
 /**
diff --git a/parser.c b/parser.c
index fc8e59d..f7d971f 100644
--- a/parser.c
+++ b/parser.c
@@ -10336,6 +10336,7 @@
 	               const xmlChar *ID, xmlNodePtr *lst) {
     xmlParserCtxtPtr ctxt;
     xmlDocPtr newDoc;
+    xmlNodePtr newRoot;
     xmlSAXHandlerPtr oldsax = NULL;
     int ret = 0;
     xmlChar start[4];
@@ -10372,8 +10373,8 @@
     if (ctx->myDoc->URL != NULL) {
 	newDoc->URL = xmlStrdup(ctx->myDoc->URL);
     }
-    newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
-    if (newDoc->children == NULL) {
+    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
+    if (newRoot == NULL) {
 	ctxt->sax = oldsax;
 	xmlFreeParserCtxt(ctxt);
 	newDoc->intSubset = NULL;
@@ -10381,6 +10382,7 @@
         xmlFreeDoc(newDoc);
 	return(-1);
     }
+    xmlAddChild((xmlNodePtr) newDoc, newRoot);
     nodePush(ctxt, newDoc->children);
     if (ctx->myDoc == NULL) {
 	ctxt->myDoc = newDoc;
@@ -10515,6 +10517,7 @@
 		      const xmlChar *ID, xmlNodePtr *list) {
     xmlParserCtxtPtr ctxt;
     xmlDocPtr newDoc;
+    xmlNodePtr newRoot;
     xmlSAXHandlerPtr oldsax = NULL;
     xmlParserErrors ret = XML_ERR_OK;
     xmlChar start[4];
@@ -10578,8 +10581,8 @@
     if (doc->URL != NULL) {
 	newDoc->URL = xmlStrdup(doc->URL);
     }
-    newDoc->children = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
-    if (newDoc->children == NULL) {
+    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
+    if (newRoot == NULL) {
 	if (sax != NULL)
 	    ctxt->sax = oldsax;
 	ctxt->node_seq.maximum = 0;
@@ -10591,12 +10594,13 @@
         xmlFreeDoc(newDoc);
 	return(XML_ERR_INTERNAL_ERROR);
     }
+    xmlAddChild((xmlNodePtr) newDoc, newRoot);
     nodePush(ctxt, newDoc->children);
     if (doc == NULL) {
 	ctxt->myDoc = newDoc;
     } else {
 	ctxt->myDoc = doc;
-	newDoc->children->doc = doc;
+	newRoot->doc = doc;
     }
 
     /* 
@@ -10758,8 +10762,10 @@
 	const xmlChar *string, void *user_data, xmlNodePtr *lst) {
     xmlParserCtxtPtr ctxt;
     xmlDocPtr newDoc = NULL;
+    xmlNodePtr newRoot;
     xmlSAXHandlerPtr oldsax = NULL;
     xmlNodePtr content = NULL;
+    xmlNodePtr last = NULL;
     int size;
     xmlParserErrors ret = XML_ERR_OK;
 
@@ -10806,10 +10812,10 @@
     } else {
 	ctxt->myDoc = oldctxt->myDoc;
         content = ctxt->myDoc->children;
+	last = ctxt->myDoc->last;
     }
-    ctxt->myDoc->children = xmlNewDocNode(ctxt->myDoc, NULL,
-	                                  BAD_CAST "pseudoroot", NULL);
-    if (ctxt->myDoc->children == NULL) {
+    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
+    if (newRoot == NULL) {
 	ctxt->sax = oldsax;
 	ctxt->dict = NULL;
 	xmlFreeParserCtxt(ctxt);
@@ -10817,6 +10823,9 @@
 	    xmlFreeDoc(newDoc);
 	return(XML_ERR_INTERNAL_ERROR);
     }
+    ctxt->myDoc->children = NULL;
+    ctxt->myDoc->last = NULL;
+    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
     nodePush(ctxt, ctxt->myDoc->children);
     ctxt->instate = XML_PARSER_CONTENT;
     ctxt->depth = oldctxt->depth + 1;
@@ -10877,6 +10886,7 @@
     if (ctxt->myDoc != NULL) {
 	xmlFreeNode(ctxt->myDoc->children);
         ctxt->myDoc->children = content;
+        ctxt->myDoc->last = last;
     }
 	
     ctxt->sax = oldsax;
diff --git a/relaxng.c b/relaxng.c
index 8eb81ec..9c6cf2d 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -6749,7 +6749,7 @@
 }
 
 /**
- * xmlRelaxNGCheckAttributes:
+ * xmlRelaxNGCleanupAttributes:
  * @ctxt:  a Relax-NG parser context
  * @node:  a Relax-NG node
  *
diff --git a/tree.c b/tree.c
index cc2a168..87c4556 100644
--- a/tree.c
+++ b/tree.c
@@ -1119,6 +1119,10 @@
 #endif
 	return;
     }
+#ifdef LIBXML_DEBUG_RUNTIME
+    xmlDebugCheckDocument(stderr, cur);
+#endif
+
     if (cur != NULL) dict = cur->dict;
 
     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
@@ -1302,6 +1306,7 @@
 			    temp = ent->children;
 			    while (temp) {
 				temp->parent = (xmlNodePtr)ent;
+				ent->last = temp;
 				temp = temp->next;
 			    }
 			}
@@ -4414,7 +4419,7 @@
     if (root == NULL)
 	return(NULL);
     xmlUnlinkNode(root);
-    root->doc = doc;
+    xmlSetTreeDoc(root, doc);
     root->parent = (xmlNodePtr) doc;
     old = doc->children;
     while (old != NULL) {
@@ -6207,10 +6212,17 @@
     while (prop != NULL) {
         if ((xmlStrEqual(prop->name, name)) &&
 	    (prop->ns == NULL)) {
-	    if (prev == NULL)
+	    if (prev == NULL) {
 		node->properties = prop->next;
-	    else
+		if (prop->next != NULL)
+		    prop->next->prev = NULL;
+	    } else {
 		prev->next = prop->next;
+		if (prop->next != NULL)
+		    prop->next->prev = NULL;
+	    }
+	    prop->next = NULL;
+	    prop->prev = NULL;
 	    xmlFreeProp(prop);
 	    return(0);
 	}
@@ -6242,10 +6254,17 @@
     while (prop != NULL) {
         if ((xmlStrEqual(prop->name, name)) &&
 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))) {
-	    if (prev == NULL)
+	    if (prev == NULL) {
 		node->properties = prop->next;
-	    else
+		if (prop->next != NULL)
+		    prop->next->prev = NULL;
+	    } else {
 		prev->next = prop->next;
+		if (prop->next != NULL)
+		    prop->next->prev = NULL;
+	    }
+	    prop->next = NULL;
+	    prop->prev = NULL;
 	    xmlFreeProp(prop);
 	    return(0);
 	}
diff --git a/xpath.c b/xpath.c
index c55958d..89a8e28 100644
--- a/xpath.c
+++ b/xpath.c
@@ -254,7 +254,7 @@
 }
 
 /**
- * xmlXPathErrMemory:
+ * xmlXPathPErrMemory:
  * @ctxt:  an XPath parser context
  * @extra:  extra informations
  *