applied an old patch from Lukas Schroeder to track node creation and

* global.data globals.c tree.c include/libxml/globals.h: applied
  an old patch from Lukas Schroeder to track node creation and
  destruction. Probably missing a lot of references at the moment
  and not usable reliably.
Daniel
diff --git a/ChangeLog b/ChangeLog
index c1cc0cf..360b36d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Jan  1 21:57:28 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+	* global.data globals.c tree.c include/libxml/globals.h: applied
+	  an old patch from Lukas Schroeder to track node creation and
+	  destruction. Probably missing a lot of references at the moment
+	  and not usable reliably.
+
 Wed Jan  1 20:12:07 CET 2003 Daniel Veillard <daniel@veillard.com>
 
 	* NEWS doc/Makefile.am doc/news.xsl: generate the NEWS file
diff --git a/global.data b/global.data
index 43d2fb5..6b170dd 100644
--- a/global.data
+++ b/global.data
@@ -20,3 +20,5 @@
 #const xmlChar,xmlStringText,[]
 #const xmlChar,xmlStringTextNoenc,[]
 int,xmlSubstituteEntitiesDefaultValue
+xmlRegisterNodeFunc,xmlRegisterNodeDefaultValue
+xmlDeregisterNodeFunc,xmlDeregisterNodeDefaultValue
diff --git a/globals.c b/globals.c
index 72865c3..7244692 100644
--- a/globals.c
+++ b/globals.c
@@ -219,6 +219,9 @@
  */
 int xmlSubstituteEntitiesDefaultValue = 0;
 
+xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
+xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
+
 /*
  * Error handling
  */
@@ -450,8 +453,40 @@
     gs->xmlPedanticParserDefaultValue = 0;
     gs->xmlSaveNoEmptyTags = 0;
     gs->xmlSubstituteEntitiesDefaultValue = 0;
+
+    gs->xmlRegisterNodeDefaultValue = NULL;
+    gs->xmlDeregisterNodeDefaultValue = NULL;
 }
 
+/**
+ * xmlRegisterNodeDefault
+ * @func: function pointer to the new RegisterNodeFunc
+ *
+ */
+xmlRegisterNodeFunc
+xmlRegisterNodeDefault(xmlRegisterNodeFunc func)
+{
+    xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue;
+    
+    xmlRegisterNodeDefaultValue = func;
+    return(old);
+}
+
+/**
+ * xmlDeegisterNodeDefault
+ * @func: function pointer to the new DeregisterNodeFunc
+ *
+ */
+xmlDeregisterNodeFunc
+xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+{
+    xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue;
+    
+    xmlDeregisterNodeDefaultValue = func;
+    return(old);
+}
+
+
 #ifdef LIBXML_DOCB_ENABLED
 #undef	docbDefaultSAXHandler
 xmlSAXHandler *
@@ -651,3 +686,21 @@
     else
 	return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue);
 }
+
+#undef	xmlRegisterNodeDefaultValue
+xmlRegisterNodeFunc *
+__xmlRegisterNodeDefaultValue(void) {
+    if (IS_MAIN_THREAD)
+	return (&xmlRegisterNodeDefaultValue);
+    else
+	return (&xmlGetGlobalState()->xmlRegisterNodeDefaultValue);
+}
+
+#undef	xmlDeregisterNodeDefaultValue
+xmlDeregisterNodeFunc *
+__xmlDeregisterNodeDefaultValue(void) {
+    if (IS_MAIN_THREAD)
+	return (&xmlDeregisterNodeDefaultValue);
+    else
+	return (&xmlGetGlobalState()->xmlDeregisterNodeDefaultValue);
+}
diff --git a/include/libxml/globals.h b/include/libxml/globals.h
index fc6c01e..ce98a11 100644
--- a/include/libxml/globals.h
+++ b/include/libxml/globals.h
@@ -52,6 +52,11 @@
 #undef	xmlRealloc
 #undef	xmlSaveNoEmptyTags
 #undef	xmlSubstituteEntitiesDefaultValue
+#undef xmlRegisterNodeDefaultValue
+#undef xmlDeregisterNodeDefaultValue
+
+typedef void (*xmlRegisterNodeFunc)(xmlNodePtr node);
+typedef void (*xmlDeregisterNodeFunc)(xmlNodePtr node);
 
 typedef struct _xmlGlobalState xmlGlobalState;
 typedef xmlGlobalState *xmlGlobalStatePtr;
@@ -89,6 +94,9 @@
 	int xmlSaveNoEmptyTags;
 	int xmlIndentTreeOutput;
 	const char *xmlTreeIndentString;
+
+  	xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
+  	xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
 };
 
 #ifdef __cplusplus
@@ -101,6 +109,9 @@
 
 void	xmlInitializeGlobalState(xmlGlobalStatePtr gs);
 
+xmlRegisterNodeFunc xmlRegisterNodeDefault(xmlRegisterNodeFunc func);
+xmlDeregisterNodeFunc xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func);
+
 /*
  * In general the memory allocation entry points are not kept
  * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED
@@ -329,6 +340,22 @@
 LIBXML_DLL_IMPORT extern int xmlSubstituteEntitiesDefaultValue;
 #endif
 
+extern xmlRegisterNodeFunc *__xmlRegisterNodeDefaultValue(void);
+#ifdef LIBXML_THREAD_ENABLED
+#define xmlRegisterNodeDefaultValue \
+(*(__xmlRegisterNodeDefaultValue()))
+#else
+LIBXML_DLL_IMPORT extern xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
+#endif
+
+extern xmlDeregisterNodeFunc *__xmlDeregisterNodeDefaultValue(void);
+#ifdef LIBXML_THREAD_ENABLED
+#define xmlDeregisterNodeDefaultValue \
+(*(__xmlDeregisterNodeDefaultValue()))
+#else
+LIBXML_DLL_IMPORT extern xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tree.c b/tree.c
index 67b7d16..7df24d5 100644
--- a/tree.c
+++ b/tree.c
@@ -338,6 +338,8 @@
 	doc->extSubset = cur;
     cur->doc = doc;
 
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -463,6 +465,10 @@
 #endif
 	return;
     }
+
+    if (xmlDeregisterNodeDefaultValue)
+	xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
+
     if (cur->children != NULL) {
 	xmlNodePtr next, c = cur->children;
 
@@ -530,6 +536,9 @@
     cur->compression = -1; /* not initialized */
     cur->doc = cur;
     cur->charset = XML_CHAR_ENCODING_UTF8;
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -550,6 +559,10 @@
 #endif
 	return;
     }
+
+    if (xmlDeregisterNodeDefaultValue)
+	xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
+
     /*
      * Do this before freeing the children list to avoid ID lookups
      */
@@ -1127,6 +1140,9 @@
 	    cur->prev = prev;
 	}
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -1204,6 +1220,9 @@
 	    cur->prev = prev;
 	}
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -1333,6 +1352,9 @@
 	    tmp = tmp->next;
 	}
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -1374,6 +1396,10 @@
 #endif
 	return;
     }
+
+    if (xmlDeregisterNodeDefaultValue)
+	xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
+
     /* Check for ID removal -> leading to invalid references ! */
     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
 	((cur->parent->doc->intSubset != NULL) ||
@@ -1471,6 +1497,9 @@
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
     return(cur);
 }
 
@@ -1509,6 +1538,9 @@
     
     cur->name = xmlStrdup(name);
     cur->ns = ns;
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1579,6 +1611,7 @@
 	    UPDATE_LAST_CHILD_AND_PARENT(cur)
 	}
     }
+
     return(cur);
 }
 
@@ -1667,6 +1700,9 @@
     cur->type = XML_DOCUMENT_FRAG_NODE;
 
     cur->doc = doc;
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1697,6 +1733,9 @@
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1797,6 +1836,9 @@
 	    cur->name = xmlStrndup(name, len);
     } else
 	cur->name = xmlStrdup(name);
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1848,6 +1890,9 @@
 	cur->children = (xmlNodePtr) ent;
 	cur->last = (xmlNodePtr) ent;
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1896,6 +1941,9 @@
     if (content != NULL) {
 	cur->content = xmlStrndup(content, len);
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1945,6 +1993,9 @@
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -1977,6 +2028,9 @@
     if (content != NULL) {
 	cur->content = xmlStrndup(content, len);
     }
+
+    if (xmlRegisterNodeDefaultValue)
+	xmlRegisterNodeDefaultValue(cur);
     return(cur);
 }
 
@@ -2398,6 +2452,9 @@
     /*
      * add the first element at the end of the children list.
      */
+    if (cur->parent == parent)
+	return(cur);
+
     if (parent->children == NULL) {
         parent->children = cur;
     } else {
@@ -2407,7 +2464,7 @@
 	if ((cur->type == XML_TEXT_NODE) && 
 	    (parent->last->type == XML_TEXT_NODE) &&
 	    (cur->name == parent->last->name)) {
-	    xmlNodeAddContent(parent->last, cur->content);
+    	    xmlNodeAddContent(parent->last, cur->content);
 	    /*
 	     * if it's the only child, nothing more to be done.
 	     */
@@ -2477,13 +2534,15 @@
      */
     if (cur->type == XML_TEXT_NODE) {
 	if ((parent->type == XML_TEXT_NODE) &&
-	    (parent->content != NULL)) {
+	    (parent->content != NULL) &&
+	    (parent != cur)) {
 	    xmlNodeAddContent(parent, cur->content);
 	    xmlFreeNode(cur);
 	    return(parent);
 	}
 	if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
-	    (parent->last->name == cur->name)) {
+	    (parent->last->name == cur->name) &&
+	    (parent->last != cur)) {
 	    xmlNodeAddContent(parent->last, cur->content);
 	    xmlFreeNode(cur);
 	    return(parent->last);
@@ -2493,16 +2552,23 @@
     /*
      * add the new element at the end of the children list.
      */
+    prev = cur->parent;
     cur->parent = parent;
     if (cur->doc != parent->doc) {
 	xmlSetTreeDoc(cur, parent->doc);
     }
+    /* this check prevents a loop on tree-traversions if a developer
+     * tries to add a node to its parent multiple times
+     */
+    if (prev == parent)
+	return(cur);
 
     /*
      * Coalescing
      */
     if ((parent->type == XML_TEXT_NODE) &&
-	(parent->content != NULL)) {
+	(parent->content != NULL) &&
+	(parent != cur)) {
 	xmlNodeAddContent(parent, cur->content);
 	xmlFreeNode(cur);
 	return(parent);
@@ -2588,6 +2654,10 @@
         next = cur->next;
 	/* unroll to speed up freeing the document */
 	if (cur->type != XML_DTD_NODE) {
+
+	    if (xmlDeregisterNodeDefaultValue)
+		xmlDeregisterNodeDefaultValue(cur);
+
 	    if ((cur->children != NULL) &&
 		(cur->type != XML_ENTITY_REF_NODE))
 		xmlFreeNodeList(cur->children);
@@ -2655,6 +2725,7 @@
 #endif
 	return;
     }
+
     /* use xmlFreeDtd for DTD nodes */
     if (cur->type == XML_DTD_NODE) {
 	xmlFreeDtd((xmlDtdPtr) cur);
@@ -2668,6 +2739,10 @@
 	xmlFreeProp((xmlAttrPtr) cur);
 	return;
     }
+
+    if (xmlDeregisterNodeDefaultValue)
+	xmlDeregisterNodeDefaultValue(cur);
+
     if ((cur->children != NULL) &&
 	(cur->type != XML_ENTITY_REF_NODE))
 	xmlFreeNodeList(cur->children);